C20 Tree그리드에서 체크셀렌더러 사용.
들어가며
이번 강좌에서는 상,하위 노드의 check/uncheck에 따라 상,하위 노드의 체크를 조작하는 방법을 배워보도록 하겠습니다.
이론
업무화면을 개발하다보면 트리구조의 메뉴화면이 필요한 경우가 있을 것입니다.
예를들어 상위노드를 체크하는 경우 하위노드를 일괄로 check/uncheck하거나 반대로 하위노드를 check/uncheck하는 경우 그 하위노드의 형제노드(sibling node)의 체크 상태에 따라
부모 노드의 체크 여부를 조작하는 것.
리얼그리드에서는 아래의 두가지 방법을 이용하여 해당 업무를 처리할 수 있습니다.
- 셀 렌더러중 하나인 CheckCellRenderer를 이용하는 방법
- 그리드의 왼쪽에 위치한 CheckBar를 이용하는 방법
이번 강좌에서는 1번인 체크 셀 렌더러를 이용하여 트리그리드의 상,하위 노드를 조작해보도록 하겠습니다.
컬럼과 필드는 아래와 같이 설정합니다.
//필드 배열 객체를 생성합니다. var fields = [{ "fieldName": "treeNode" }, { "fieldName": "menuName" }, { "fieldName": "auth" }]; dataProvider.setFields(fields); //필드와 연결된 컬럼 배열 객체를 생성합니다. var columns = [ "name": "menuName", "fieldName": "menuName", "width": 350, "header": { "text": "메뉴명" } }, { "name": "auth", "fieldName": "auth", "width": 150, "header": { "text": "권한여부" }, "editable": false, "renderer": { "type": "check", "shape": "box", "editable": true, "startEditOnClick": true, "trueValues": "Y", "falseValues": "N" }, }]; gridView.setColumns(columns);
treeNode필드는 트리 노드의 구성정보가 들어갈 필드입니다. 화면에 표시되는 필드는 menuName, auth 필드 입니다.
사용할 예제의 데이터는 아래와 같은 형태 입니다.
var data = [ ["0", "\\", "Y"], ["0.001", "영업관리", "Y"], ["0.001.001", "영업관리1-중분류", "Y"], ["0.001.001.001", "영업관리1-소분류1", "Y"], ["0.001.001.002", "영업관리1-소분류2", "Y"], ["0.001.001.003", "영업관리1-소분류3", "Y"], ["0.002", "영업회계", "Y"], ["0.002.001", "영업회계1-중분류", "Y"], ["0.002.001.001", "영업회계1-소분류1", "Y"], ["0.002.001.002", "영업회계1-소분류2", "Y"], ["0.002.002", "영업회계2-중분류", "Y"], ["0.002.002.001", "영업회계2-소분류1", "Y"], ["0.002.002.002", "영업회계2-소분류2", "Y"], ["0.002.002.003", "영업회계2-소분류3", "Y"], ["0.002.002.004", "영업회계2-소분류4", "Y"] ]; dataProvider.setRows(data, "treeNode", true, "", "");
이렇게 표시된 그리드에서 auth(권한여부) 컬럼셀을 클릭하여 값을 변경하는 경우 트리 그리드에서는 onCellEdited() 이벤트가 발생하게 됩니다. 해당 이벤트 안에서 체크된 값에 따라 각 노드를 확인하고 상,하위 노드의 체크를 제어하면 됩니다.
실습에서는 아래 API들을 이용하여 노드정보를 획득하고 체크값들을 제어해보도록 하겠습니다.
부모/자식 ID를 가져오는 API들
- 조상: dataProvider.getAncestors()
- 부모: dataProvider.getParent()
- 자식: dataProvider.getChildren()
- 자손: dataProvider.getDescendants()
실습
-
화면에 표시되고 있는 “권한여부” 컬럼의 체크박스를 클릭하여 체크값 변경 후 다른 행의 expander(+/-)를 클릭해보세요. 체크한 행이 현재 편집중이기에 expander가 동작하지 않습니다.
-
체크한 값을 commit()시켜 편집상태를 종료하려면 값이 편집되었을때 발생하는 onCellEdited()안에 아래와 같이 grid.commit()을 추가하여야 합니다.
//셀 편집 후 commit() $("#btnSetOnCellEdited").click(function () { gridView.onCellEdited = function (grid, itemIndex, dataRow, field) { grid.commit(true); }; });
-
“권한여부” 컬럼의 체크박스를 클릭하여 체크값 변경 후 다른 행의 expander(+/-)를 클릭해보세요. 잘 동작합니다.
-
“auth” 컬럼을 체크하였을때 하위자손 노드들은 현재의 체크값과 같은 값을 set 해주면 됩니다. 상위 노드들은 체크한 형제노드들의 값이 모두 같으면 체크해주고 하나라도 다르면 체크해제를 set 해주면 됩니다. 해당 코드는 아래와 같습니다.
//체크셀렌더러 체크 제어 function checkNode(provider, dataRow, checked) { //형제노드체크 후 부모노드 체크 checkSiblingNode(provider, dataRow, checked); //자손노드체크 var desRows = provider.getDescendants(dataRow); for (var i in desRows) { dataProvider.setValue(desRows[i], "auth", checked); } }; function checkSiblingNode(provider, dataRow, checked) { //부모노드 var parent = provider.getParent(dataRow); //형제노드들 var sibling = provider.getChildren(parent); var index = sibling.indexOf(dataRow); //자기자신은 제외 if (index !== -1) sibling.splice(index, 1); if (checked == "Y") { var result = true; for (var i in sibling) { var value = dataProvider.getValue(sibling[i], "auth"); if (checked != value) { result = false; break; } } checked = result ? "Y" : "N"; } else { checked = "N"; } provider.setValue(parent, "auth", checked); if (parent > -1) checkSiblingNode(provider, parent, checked); }
-
onCellEdited()안에 위에서 작성한 코드를 추가합니다.
$("#btnSetOnCellEdited1").click(function () { //체크셀렌더러 체크 제어 function checkNode(provider, dataRow, checked) { //형제노드체크 후 부모노드 체크 checkSiblingNode(provider, dataRow, checked); //자손노드체크 var desRows = provider.getDescendants(dataRow); for (var i in desRows) { dataProvider.setValue(desRows[i], "auth", checked); } }; function checkSiblingNode(provider, dataRow, checked) { //부모노드 var parent = provider.getParent(dataRow); //형제노드들 var sibling = provider.getChildren(parent); var index = sibling.indexOf(dataRow); //자기자신은 제외 if (index !== -1) sibling.splice(index, 1); if (checked == "Y") { var result = true; for (var i in sibling) { var value = dataProvider.getValue(sibling[i], "auth"); if (checked != value) { result = false; break; } } checked = result ? "Y" : "N"; } else { checked = "N"; } provider.setValue(parent, "auth", checked); if (parent > -1) checkSiblingNode(provider, parent, checked); }; gridView.onCellEdited = function (grid, itemIndex, dataRow, field) { grid.commit(true); var provider = grid.getDataSource(); var fieldName = dataProvider.getOrgFieldName(field); if (fieldName == 'auth') { checkNode(provider, dataRow, grid.getValue(itemIndex, field)); } }; });
실행화면
-
화면에 표시되고 있는 “권한여부” 컬럼의 체크박스를 클릭하여 체크값 변경 후 다른 행의 expander(+/-)를 클릭해보세요. 체크한 행이 현재 편집중이기에 expander가 동작하지 않습니다.
-
버튼을 클릭하여 onCellEdited() 안에 commit() 적용하기
-
화면에 표시되고 있는 “권한여부” 컬럼의 체크박스를 클릭하여 체크값 변경 후 다른 행의 expander(+/-)를 클릭해보세요. 잘 동작합니다.
-
CheckNode() 정의하기
-
“권한여부” 컬럼의 체크박스를 클릭하여 체크박스 값이 잘 연동되는지 확인하세요.
전체 소스코드
SCRIPT
<script type="text/javascript" src="/script/realgridjs-lic.js"></script> <script type="text/javascript" src="/script/realgridjs_eval.1.1.27.min.js"></script> <script type="text/javascript" src="/script/realgridjs-api.1.1.27.js"></script> <script> var gridView; var dataProvider; $(document).ready( function(){ RealGridJS.setTrace(false); RealGridJS.setRootContext("/script"); dataProvider = new RealGridJS.LocalTreeDataProvider(); gridView = new RealGridJS.TreeView("realgrid"); gridView.setDataSource(dataProvider); //필드 배열 객체를 생성합니다. var fields = [{ "fieldName": "treeNode" }, { "fieldName": "menuName" }, { "fieldName": "auth" }]; //DataProvider의 setFields함수로 필드를 입력합니다. dataProvider.setFields(fields); //필드와 연결된 컬럼 배열 객체를 생성합니다. var columns = [{ "name": "menuName", "fieldName": "menuName", "width": 350, "header": { "text": "메뉴명" } }, { "name": "auth", "fieldName": "auth", "width": 150, "header": { "text": "권한여부" }, "editable": false, "renderer": { "type": "check", "shape": "box", "editable": true, "startEditOnClick": true, "trueValues": "Y", "falseValues": "N" } }]; //컬럼을 GridView에 입력 합니다. gridView.setColumns(columns); var data = [ ["0", "\\", "Y"], ["0.001", "영업관리", "Y"], ["0.001.001", "영업관리1-중분류", "Y"], ["0.001.001.001", "영업관리1-소분류1", "Y"], ["0.001.001.002", "영업관리1-소분류2", "Y"], ["0.001.001.003", "영업관리1-소분류3", "Y"], ["0.002", "영업회계", "Y"], ["0.002.001", "영업회계1-중분류", "Y"], ["0.002.001.001", "영업회계1-소분류1", "Y"], ["0.002.001.002", "영업회계1-소분류2", "Y"], ["0.002.002", "영업회계2-중분류", "Y"], ["0.002.002.001", "영업회계2-소분류1", "Y"], ["0.002.002.002", "영업회계2-소분류2", "Y"], ["0.002.002.003", "영업회계2-소분류3", "Y"], ["0.002.002.004", "영업회계2-소분류4", "Y"] ]; dataProvider.setRows(data, "treeNode", true, "", ""); gridView.expandAll(); //셀 편집 후 commit() $("#btnSetOnCellEdited").click(function () { gridView.onCellEdited = function (grid, itemIndex, dataRow, field) { grid.commit(true); }; }); $("#btnSetOnCellEdited1").click(function () { function checkNode(provider, dataRow, checked) { //형제노드체크 후 부모노드 체크 checkSiblingNode(provider, dataRow, checked); //자식노드체크 var desRows = provider.getDescendants(dataRow); for (var i in desRows) { dataProvider.setValue(desRows[i], "auth", checked); } }; function checkSiblingNode(provider, dataRow, checked) { //부모노드 var parent = provider.getParent(dataRow); //형제노드 var sibling = provider.getChildren(parent); var index = sibling.indexOf(dataRow); //자기자신은 제외 if (index !== -1) sibling.splice(index, 1); if (checked == "Y") { var result = true; for (var i in sibling) { var value = dataProvider.getValue(sibling[i], "auth"); if (checked != value) { result = false; break; } } checked = result ? "Y" : "N"; } else { checked = "N"; } provider.setValue(parent, "auth", checked); if (parent > -1) checkSiblingNode(provider, parent, checked); } gridView.onCellEdited = function (grid, itemIndex, dataRow, field) { grid.commit(true); var provider = grid.getDataSource(); var fieldName = dataProvider.getOrgFieldName(field); if (fieldName == 'auth') { checkNode(provider, dataRow, grid.getValue(itemIndex, field)); } }; }); }); </script>
HTML
<div id="realgrid" style="width: 90%; height: 380px;"></div> <p></p> 1. 화면에 표시되고 있는 "권한여부" 컬럼의 체크박스를 클릭하여 체크값 변경 후 다른 행의 expander(+/-)를 클릭해보세요. 체크한 행이 현재 편집중이기에 expander가 동작하지 않습니다. 2. <button type="button" class="btn btn-primary btn-xs" id="btnSetOnCellEdited">grid.commit()</button> 버튼을 클릭하여 onCellEdited() 안에 commit() 적용하기 3. 화면에 표시되고 있는 "권한여부" 컬럼의 체크박스를 클릭하여 체크값 변경 후 다른 행의 expander(+/-)를 클릭해보세요. 잘 동작합니다. 4. CheckNode() 정의하기 5. <button type="button" class="btn btn-primary btn-xs" id="btnSetOnCellEdited1">onCellEdited() 안에 CheckNode 적용하기</button> 6. "권한여부" 컬럼의 체크박스를 클릭하여 체크박스 값이 잘 연동되는지 확인하세요.
참조