> For the complete documentation index, see [llms.txt](https://tech.x2bee.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tech.x2bee.com/dev-guide/developer-guide-en/pjt-prepare/ui-ux-guide/screen-detail-guide/realgrid.md).

# RealGrid

The BO template used an external JavaScript library called RealGrid for list lookups and list data management (create/update/delete). ※ This document is based on the legacy X2BEE 3.0 BO (Thymeleaf templates). The current 3.1 BO is Next.js-based and uses MUI X Premium DataGrid (@mui/x-data-grid-premium 7.21.0), so the RealGrid/HTML/JS examples below are for legacy reference only.

Since it was used extensively throughout the BO program, it provides a development structure and convenience features for utilizing the grid.

## realgrid HTML

Defines the form to be used in the grid and the location where the grid will be created.

Imports the JS file that defines the events for grid creation and data manipulation used within the grid.

```html
<!-- B 영역 : (그리드) 하위 전시 카테고리 매장 조회 목록 -->
<div class="grid-cont" id="subCategoryGridArea"> <!-- 그리드 <div> 영역. realgrid 컨트롤 + 데이터 조회/수정을 위한 <form> + 조작버튼 + 페이징정보 를 포함한 전체 <div> 영역입니다. -->
   <div class="grid" style="overflow: hidden;">
       <div class="grid-head">
           <form name="subCategoryGridForm" id="subCategoryGridForm"> <!-- 데이터 조회/수정 시 데이터가 전송 시 realgrid에서 사용된 <form>입니다. -->
               <input type="hidden" id="subCategoryGrid_uprDispCtgNo" name="uprDispCtgNo">
               <input type="hidden" id="subCategoryGrid_siteNo" name="siteNo">
               <input type="hidden" id="subCategoryGrid_dpmlNo" name="dpmlNo">
               <input type="hidden" id="subCategoryGrid_shopTypCd" name="shopTypCd">
               <input type="hidden" id="subCategoryGrid_thnCtgNo" name="thnCtgNo">
           </form>
           <div class="title-area">
               <h2 class="title" th:text=“#{'displayCategoryMgmt.subCategoryGrid.title'}" />
           </div>
           <div class="option-area">
               <div class="edit-option">
                   <div class="button-group"> <!-- 데이터 조작을 위한 버튼을 표시합니다. 버튼 클릭 시 자바스크립트 코드는 개별적으로 작성해야합니다. -->
                       <a href="#" class="button inside" id="btn_subCategoryGrid_add">
                           <span class="text" th:text="#{'adminCommon.grid.button.add.row'}" />
                       </a>
                       <a href="#" class="button inside" id="btn_subCategoryGrid_save">
                           <span class="text" th:text=“#{'adminCommon.button.save'}" />
                       </a>
                   </div>
               </div>
               <div class="page-option" grid-id="subCategoryGrid"> <!-- 페이징 정보가 표시됩니다. -->
                   <span class='total'>총 <span id="subCategoryGrid-totalcount">0</span>건</span>
               </div>
           </div>
       </div>
       <div class="grid-body with-head vh2">
           <div id="subCategoryGrid" realgrid class="vh2"></div> <!-- realgrid 컨트롤이 표시되는 영역입니다. -->
       </div>
   </div>
</div>
<!-- B 영역 : (그리드) 하위 전시 카테고리 매장 조회 목록 -->

<!-- 자바스크립트 파일 지정 및 초기화 스크립트 실행 -->
<script type="text/javascript" th:src="${@domainConfig.getProperty('jsUrl')} + 'system/bwGrid.eventHandler.js'"></script>
<script type="text/javascript" th:src="${@domainConfig.getProperty('jsUrl')} + 'system/bwGrid.provider.js'"></script>

<script type="text/javascript">
   $(function() {
       bwGrid.eventhandler.init();
   });
</script>
```

## realgrid provider.js

When using realgrid in x2bee, you must write provider.js and eventHandler.js.

This explains the provider.js file.

provider.js defines the overall content and properties of the data that will go into the grid.

The properties to be defined include field names, column properties, data validation, grid properties, and more.

```javascript
$.namespace("bwGrid.settings");
bwGrid.settings = { //그리드의 필드명지정
   fields : [ {
       fieldName : "bwSeq"
   }, {
       fieldName : "sysModId"
   } ],
   columns : [ { //컴럼속성지정
       name : "bwNm",
       fieldName : "bwNm",
       header : {
           text : col.bwNm + "*"
       },
       width : 200,
       editable : true,
       styleName : "left-column",
       editor :{
           maxLength: 30
       }
   }, {
      ...
   } ],
   validations : [ //데이터 검증 지정
       {
           fieldName : "bwNm",
           criteria : "value === undefined || value.trim() === ''"  ,
           error : { level : "error", message : alertMsg.bwNmMessage }
       }
   ],
   props : { //그리드 속성지정, api URL 지정등의 작업 수행
       paging : true,
       width : "100%",
       autoFitHeight : true,
       checkbox : true,
       crud : true,
       form : "bwGridForm", //데이터 조회/수정 시, 데이터 전송 시 realgrid 에서 사용될 form ID 지정
       sumRowVisible : false,
       action : _baseUrl + "system/badWordMgmt.getBadWordList.do", //조회 시 url 지정
       saveAction : _baseUrl + "system/badWordMgmt.saveBadWord.do" //저장 시 url 지정
       //rows : [100,500,1000] //rows 설정시 rowsPerPage 설정 가능, default [100,500,1000,5000,10000]
   }
};
```

## realgrid eventHandler.js

This explains the eventHandler.js file.

eventHandler specifies the processing—insert, update, delete, etc.—for data that the user changes within the grid.

Defines the grid's default configuration script, button events within the grid, and the functions used.

```javascript
$.namespace("bwGrid.eventhandler");

$('#btn_grid_remove').click(function() {
    self.grid.cancel();
    self.onDelete();
});

$("#btn_grid_reset").click(function() {
    self.onReset();
});

$('#btn_grid_save').click(function() {
    self.onSave();
});

$("#bwGridForm").keypress(function (e){
    if (e.which == 13){
        $('#btn_search').click();
        window.event.returnValue=false;
    }
});

}, // (end init or surrounding object)
gridEvent : { //그리드 이벤트 설정
    afterSaveSuccess : function(eventHandler, mainGridName, gridNames, data){
        openToast(data.message);
        if(data.succeeded){
            eventHandler.onSearch(0,false);
       }
    },
    onEditRowChanged: function (grid, itemIndex, dataRow, field, oldValue, newValue) {
        var rowCnt = grid.getItemCount();
        var editRowIndex = itemIndex;

        var rowData = "";
        for (var rowIndex = 0; rowIndex < rowCnt; rowIndex++) {
            if (rowIndex == editRowIndex) continue;

            rowData = grid.getValue(rowIndex, "bwNm");
            if ( newValue === rowData ) {
                alert(alertMsg.dupMessage);
                grid.cancel();
                break;
            }
        }
    }
},
onAdd : function() { //함수 정의
    var self = this;
    var grid = self.grid;
    grid.commit(true);

    var defaultValues = { useYn : "Y" };
    self.defaultHandler.onAdd(grid, defaultValues);
},
onDelete : function() {
    var self = this;
    var grid = self.grid;

    var checkedItems = grid.getCheckedItems();
    if (!checkedItems.length) {
        alert(alertMsg.rowCheckMsg);
        return;
    }

    self.defaultHandler.onDelete(grid);
},
onReset : function() {
    var grid = this.grid;
    this.defaultHandler.onCancel(grid);
},
onSearch : function(pageIdx,isOpenToast){
    this.grid.cancel();
    pageIdx = !pageIdx ? 0 : pageIdx;
    var self = this;
    var pagingFunc = function(pageIdx){return self.onSearch(pageIdx);};

    this.controller.doQuery(this, "", pageIdx, pagingFunc, false , isOpenToast);
},
onSave : function() {
    var grid = this.grid;
    this.controller.doSave(this, grid.localId);
}
};
```
