> 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/pjt-prepare/ui-ux/undefined/undefined-3.md).

# 리얼그리드

BO 템플릿은 목록조회 및 목록데이터 관리(입력/수정/삭제)에 리얼그리드(RealGrid)라는 외부 자바스크립트 라이브러리를 사용했습니다. ※ 본 문서는 구 X2BEE 3.0 BO(Thymeleaf 템플릿) 기준입니다. 현행 3.1 BO는 Next.js 기반으로 MUI X Premium DataGrid(@mui/x-data-grid-premium 7.21.0)를 사용하므로, 아래 RealGrid·HTML·JS 예시는 레거시 참고용입니다.

BO 프로그램 전반에 걸쳐서 광범위하게 사용되고 있어서, 그리드를 활용하기 위한 개발구조 및 편의기능을 제공하고 있습니다.

## realgrid HTML

그리드에 사용될 form과 그리드가 생성될 위치를 정의합니다.

그리드 생성과 그리드 내에서 사용하는 데이터 조작을 위한 이벤트가 정의된 js파일을 가져옵니다.

```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

x2bee에서 realgrid 사용 시 provider.js와 eventHandler.js 를 작성해야 합니다.

provider.js 파일에 대해서 설명합니다.

provider.js 에서는 그리드 내에 들어갈 데이터의 전반적인 내용 및 속성을 정의합니다.

정의할 속성으로는 필드명, 컬럼속성, 데이터검증, 그리드속성 등이 있습니다.

```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

eventHandler.js 파일에 대해 설명합니다.

eventHandler 에서는 그리드 내에서 사용자가 변경하는 데이터에 대한 삽입,수정,삭제등의 처리를 지정합니다.

그리드 기본설정 스크립트, 그리드 내의 버튼이벤트, 사용되는 함수를 정의합니다.

```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);
}
};
```
