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


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tech.x2bee.com/dev-guide/pjt-prepare/ui-ux/undefined/undefined-3.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
