들어가며

이번 강좌에서는 A23 데이터 편집하기(Editing)에서 배워보았던 행 상태(RowState)에 대하여 조금 더 자세히 배워보도록 하겠습니다.

이론

RealGrid는 행의 상태를 관리할 수 있습니다. 이 행이 편집된 행인지, 추가된 행인지, 삭제된 행인지, 또는 추가된 후 삭제된 행인지를 확인 할 수 있습니다. 행의 상태를 관리하기 위해서는 기본적으로 dataProviderOptions의 속성중 checkStates 속성값이 true로 되어 있어야 합니다. 기본값이 true이므로 별다른 설정은 필요 없습니다.

RealGrid는 사용자의 액션(추가, 수정, 삭제)에 따라 자동으로 행 상태를 관리합니다. 또한 RealGrid는 개발자의 의도에 따라 임의로 행 상태를 관리할 수도 있습니다. 아래에서는 행 상태의 종류와 행 상태에 관련된 API를 확인해보도록 하겠습니다.

행 상태(RowState)의 종류

none : 로드된 후 변경이 없는 상태.
created : 새로 추가된 행의 상태.
updated : 로드된 후 하나 이상의 필드 값이 변경된 상태. created 행은 값이 변경 되어도 updated로 변경되지 않습니다.
deleted : 로드된 후 삭제된 행의 상태.
createAndDeleted : 추가된 후 삭제한 행의 상태.

deletedcreateAndDeleted 상태는 dataProvider.options.softDeleting 의 값이 true 일 경우에만 가질 수 있습니다. softDeleting = false 라면 행 삭제시 행 상태를 바꾸지 않고 바로 dataProvider에서 삭제하기 때문 입니다.

RowState 와 관련된 API들

  • DataProvider.setRowState(row, state, force)
    지정한 행의 RowState를 변경하는 함수입니다.
    row : 변경하려는 dataRow를 지정합니다.
    state : 변경하려는 행 상태를 지정합니다.
    force : 현재 행 상태를 관리하지 않는 상태(checkStates=false)여도 강제로 행에 rowState를 지정할 것인지의 여부

  • DataProvider.setRowStates(rows, state, force, rowEvents) 지정한 행들의 RowState를 변경하는 함수입니다.
    rows : 변경하려는 dataRows를 지정합니다.
    state : 변경하려는 행 상태를 지정합니다.
    force : 현재 행 상태를 관리하지 않는 상태(checkStates=false)여도 강제로 행에 rowState를 지정할 것인지의 여부
    rowEvents : RowState가 변경될때 onRowStateChanged() 콜백함수를 변경되는 행 수 만큼 호출되도록 할 것인지 아니면 한번만 호출되도록 할 것인지의 여부.

  • DataProvider.getRowState(row)
    지정한 행의 RowState가 무엇인지 알아볼때 사용하는 함수입니다.
    row : dataRow를 지정합니다.

  • DataProvider.getRowStateCount(rowStates)
    지정한 RowStates에 해당하는 행들의 개수가 몇개인지 알아볼때 사용하는 함수입니다.
    rowStates : 개수가 몇개인지 알려고 하는 rowState를 지정합니다. ‘created’ 같이 문자열 형태나 [‘created’, ‘updated’] 같이 array 형태의 문자열 사용이 가능합니다.

  • DataProvider.getStateRows(rowState)
    지정한 RowState에 해당하는 행들을 알고 샆을때 사용하는 함수입니다. 결과는 배열로 리턴됩니다.
    rowState : 알고싶은 행 상태를 지정합니다.

  • DataProvider.getAllStateRows()
    RowState가 ‘none’이 아닌 모든 행의 번호를 상태별로 가져옵니다. 결과값은 ‘created’, ‘updated’, ‘deleted’, ‘createAndDeleted’ 상태 이름들을 속성으로 갖는 object이며 각 속성의 값은 해당 상태의 dataRow 배열입니다.

  • DataProvider.clearRowStates(deleteRows, rowEvents)
    행들에 지정되어 있는 RowState를 모두 제거한다.
    deleteRows : false 로 지정하면 모든 행들의 RowState만 ‘none’ 상태로 변경합니다. true로 지정하면 ‘deleted’나 ‘createAndDeleted’ 상태를 갖는 행들은 실제로 dataProvider에서 삭제하며 이외의 행 상태들은 ‘none’ 상태로 변경합니다.

콜백함수

행 상태 변경시 호출되는 콜백 함수는 아래와 같습니다.

실습

실습에서는 위에서 언급한 API들을 실행해보면서 기능을 습득하고, 위에서 언급한 세 개의 콜백함수가 어느 시점에 호출되는지 확인해보도록 하겠습니다.

  1. 버튼을 클릭하면 콜백 함수를 설정합니다.

     $("#btnSetCallback").click(function () {
         dataProvider.onRowStateChanged = function (provider, row) {
             alert("onRowStateChanged 호출");
         }
    
         dataProvider.onRowStatesChanged = function (provider, rows) {
             alert("onRowStatesChanged 호출");
         }
    
         dataProvider.onRowStatesCleared = function (provider) {
             alert("onRowStatesCleared 호출");
         }
     });
  2. 버튼을 클릭하면 첫 행의 RowState를 ‘created’로 변경합니다.

     $("#btnSetRowStateCreated").click(function () {
         dataProvider.setRowState(0, 'created');
     });
  3. 버튼을 클릭하면 3 행의 RowState를 ‘updated’로 변경합니다.

     $("#btnSetRowStateUpdated").click(function () {
         dataProvider.setRowState(2, 'updated');  
     });
  4. 버튼을 클릭하면 5 행의 RowState를 ‘deleted’로 변경합니다.

     $("#btnSetRowStateDeleted").click(function () {
         dataProvider.setRowState(4, 'deleted');  
     });
  5. 버튼을 클릭하면 7 행의 RowState를 ‘createAndDeleted’로 변경합니다.

     $("#btnSetRowStateCreateAndDeleted").click(function () {
         dataProvider.setRowState(6, 'createAndDeleted');  
     });
  6. 버튼을 클릭하면 9, 10행의 상태를 ‘updated’로 변경합니다.

     $("#btnSetRowStatesT").click(function () {
         dataProvider.setRowStates([8, 9], 'updated', true, true);
     });
  7. 버튼을 클릭하면 11, 12행의 상태를 ‘updated’로 변경합니다.

     $("#btnSetRowStatesF").click(function () {
         dataProvider.setRowStates([10, 11], 'updated', true, false);
     });
  8. 버튼을 클릭하면 10행의 상태를 가져옵니다.

     $("#btnGetRowState").click(function () {
         var state = dataProvider.getRowState(9);
         alert(state);
     });
  9. 버튼을 클릭하면 ‘deleted’상태인 행의 dataRow 목록을 가져옵니다.

     $("#btnGetStateRows").click(function () {
         var dataRows = dataProvider.getStateRows('deleted');
         alert(dataRows);
     });
  10. 버튼을 클릭하면 각 RowState 상태에 해당하는 dataRow들을 가져옵니다.

    $("#btnGetAllStateRows").click(function () {
        var states = dataProvider.getAllStateRows();
        alert(JSON.stringify(states));
    });
  11. 버튼을 클릭하면 행 상태가 사라집니다.

    $("#btnClearRowStatesF").click(function () {
        dataProvider.clearRowStates(false, false);
    });
  12. 버튼을 클릭하면 행 상태가 사라집니다.

    $("#btnClearRowStatesT").click(function () {
        dataProvider.clearRowStates(true, true);
    });

실행화면

  1. 버튼을 클릭하면 콜백 함수를 설정합니다. 화면에는 아무 변화가 없습니다.

  2. 버튼을 클릭하면 첫 행의 RowState를 ‘created’로 변경합니다. (onRowStateChanged 호출)

  3. 2행을 선택 후 Ctrl+Insertkey를 입력하여 행을 추가합니다. 행 추가 후 data를 입력하고 편집까지 완료합니다. RowState를 ‘created’로 변경되는 것을 확인하세요. (onRowStateChanged 미호출, 신규 행이기때문에 행 상태가 변경 되는것이 아니기 때문입니다.)

  4. 버튼을 클릭하면 3 행의 RowState를 ‘updated’로 변경합니다. (onRowStateChanged 호출)

  5. 4행을 선택후 데이터를 수정합니다. RowState를 ‘updated’로 변경되는 것을 확인하세요. (onRowStateChanged 호출)

  6. 버튼을 클릭하면 5 행의 RowState를 ‘deleted’로 변경합니다. (onRowStateChanged 호출)

  7. 6행을 선택후 Ctrl+Delkey를 입력하여 행을 삭제합니다. RowState를 ‘deleted’로 변경되는 것을 확인하세요. (onRowStateChanged 호출)

  8. 버튼을 클릭하면 7 행의 RowState를 ‘createAndDeleted’로 변경합니다. (onRowStateChanged 호출)

  9. ‘created’ 상태인 2행을 선택 후 Ctrl+Delkey를 입력하여 행을 삭제합니다. RowState를 ‘createAndDeleted’로 변경되는 것을 확인하세요. (onRowStateChanged 호출, 3번에서는 호출되지 않았던 onRowStateChanged가 ‘created’ 상태에서 변경되었기 때문에 이번에는 호출됩니다.)

  10. 버튼을 클릭하면 9, 10행의 상태를 ‘updated’로 변경합니다. (마지막 파라메터인 rowEvent가 true 일 경우 화면이 갱신되지 않는 버그가 있습니다. 스크롤 바를 움직이면 rowState가 정상적으로 표시됩니다., onRowStateChanged 호출되어야 하나 버그로 인해 호출되지 않습니다.)

  11. 버튼을 클릭하면 11, 12행의 상태를 ‘updated’로 변경합니다. (onRowStatesChanged 호출)

  12. 버튼을 클릭하면 10행의 상태를 가져옵니다.

  13. 버튼을 클릭하면 ‘deleted’상태인 행의 dataRow 목록을 가져옵니다.

  14. 버튼을 클릭하면 각 RowState 상태에 해당하는 dataRow들을 가져옵니다.

  15. 버튼을 클릭하면 행 상태가 사라집니다. (onRowStatesCleared 호출, 첫번째 파라메터인 deleteRows가 false 이기 때문에 행 상태가 ‘deleted’, ‘createAndDeleted’인 행들이 삭제 되지 않고 RowState만 지워졌음을 확인하세요)

  16. 몇 개의 행을 Ctrl+Delkey를 입력하여 행들을 ‘deleted’ 상태로 만들고, 몇 개의 행은 값을 수정하여 ‘updated’ 상태로 만들어보세요.

  17. 버튼을 클릭하면 행 상태가 사라집니다. (‘deleted’였던 행들은 사라지고, 수정한 행 수 만큼 onRowStateChanged 호출)

전체 소스코드

SCRIPT
<link rel="stylesheet" href="/css/bootstrap.css">
<script type="text/javascript" src="/script/jquery-1.112.min.js"></script>
<script type="text/javascript" src="/script/bootstrap.min.js"></script>
<!--realgrid-->
<script type="text/javascript" src="/script/realgridjs-lic.js"></script>
<script type="text/javascript" src="/script/realgridjs_eval.1.0.14.min.js"></script>
<script type="text/javascript" src="/script/realgridjs-api.1.0.14.js"></script>

<script>
var gridView;
var dataProvider;

$(document).ready( function(){
    RealGridJS.setTrace(false);
    RealGridJS.setRootContext("/script");
    
    dataProvider = new RealGridJS.LocalDataProvider();
    gridView = new RealGridJS.GridView("realgrid");
    gridView.setDataSource(dataProvider);

    //필드 배열 객체를  생성합니다.
    var fields = [
        {
            fieldName: "field1"
        },
        {
            fieldName: "field2"
        },
        {
            fieldName: "field3"
        },
        {
            fieldName: "field4"
        },
        {
            fieldName: "field5"
        },
        {
            fieldName: "field6"
        },
        {
            fieldName: "field7"
        },
        {
            fieldName: "field8"
        },
        {
            fieldName: "field9"
        },
        {
            fieldName: "field10"
        }
    ];
    //DataProvider의 setFields함수로 필드를 입력합니다.
    dataProvider.setFields(fields);

    //필드와 연결된 컬럼 배열 객체를 생성합니다.
    var columns = [
        {
            name: "col1",
            fieldName: "field1",
            header : {
                text: "직업"
            },
            width : 60
        },
        {
            name: "col2",
            fieldName: "field2",
            header : {
                text: "성별"
            },
            width: 50
        },
        {
            name: "col3",
            fieldName: "field3",
            header : {
                text: "이름"
            },
            width: 80
        },
        {
            name: "col4",
            fieldName: "field4",
            header : {
                text: "국어"
            },
            width: 80
        },
        {
            name: "col5",
            fieldName: "field5",
            header : {
                text: "수학"
            },
            width: 80
        },
        {
            name: "col6",
            fieldName: "field6",
            header : {
                text: "민법"
            },
            width: 80
        },
        {
            name: "col7",
            fieldName: "field7",
            header : {
                text: "한국사"
            },
            width: 80
        },
        {
            name: "col8",
            fieldName: "field8",
            header : {
                text: "영어"
            },
            width: 80
        },
        {
            name: "col9",
            fieldName: "field9",
            header : {
                text: "과학"
            },
            width: 80
        },
        {
            name: "col10",
            fieldName: "field10",
            header : {
                text: "사회"
            },
            width: 80
        }
    ];
    //컬럼을 GridView에 입력 합니다.
    gridView.setColumns(columns);

    var data = [
        ["배우", "여자", "전도연", "0", "70", "90", "70", "60", "100", "80"],
        ["가수", "여자", "이선희", "1", "33", "90", "70", "60", "100", "80"],
        ["배우", "여자", "하지원", "2", "100", "90", "70", "60", "100", "80"],
        ["가수", "여자", "박정현", "3", "90", "90", "70", "60", "100", "80"],
        ["배우", "여자", "전지현", "4", "100", "90", "70", "60", "100", "80"],
        ["가수", "남자", "성시경", "7", "100", "100", "100", "100", "100", "100"],
        ["가수", "남자", "신해철", "8", "100", "100", "100", "100", "100", "100"],
        ["가수", "남자", "윤상", "9", "100", "100", "100", "100", "100", "100"],
        ["가수", "남자", "윤종신", "10", "100", "100", "100", "100", "100", "100"],
        ["가수", "여자", "이소라", "11", "100", "100", "100", "100", "100", "100"],
        ["배우", "여자", "강소라", "12", "100", "100", "100", "100", "100", "100"],
        ["가수", "남자", "타블로", "13", "100", "100", "100", "100", "100", "100"],
        ["가수", "남자", "이승환", "14", "100", "100", "100", "100", "100", "100"],
        ["가수", "남자", "토이", "15", "100", "100", "100", "100", "100", "100"]
    ];
    dataProvider.setRows(data);

    gridView.setOptions({
        indicator: {visible: true},        
        checkBar: {visible: false},
        stateBar: {visible: true},
        edit: {insertable: true, appendable: true, updatable: true, editable: true, deletable: true},
        sort: {enabled: false},
        panel: {visible: false}
    });

    dataProvider.setOptions({
        softDeleting: true
    })

    //버튼을 클릭하면 콜백 함수를 설정합니다.
    $("#btnSetCallback").click(function () {
        dataProvider.onRowStateChanged = function (provider, row) {
            alert("onRowStateChanged 호출");
        }

        dataProvider.onRowStatesChanged = function (provider, rows) {
            alert("onRowStatesChanged 호출");
        }

        dataProvider.onRowStatesCleared = function (provider) {
            alert("onRowStatesCleared 호출");
        }
    });

    //버튼을 클릭하면 첫 행의 RowState를 'created'로 변경합니다.
    $("#btnSetRowStateCreated").click(function () {
        dataProvider.setRowState(0, 'created');
    });

    //버튼을 클릭하면 3 행의 RowState를 'updated'로 변경합니다.
    $("#btnSetRowStateUpdated").click(function () {
        dataProvider.setRowState(2, 'updated');  
    });

    //버튼을 클릭하면 5 행의 RowState를 'deleted'로 변경합니다.
    $("#btnSetRowStateDeleted").click(function () {
        dataProvider.setRowState(4, 'deleted');  
    });

    //버튼을 클릭하면 7 행의 RowState를 'createAndDeleted'로 변경합니다.
    $("#btnSetRowStateCreateAndDeleted").click(function () {
        dataProvider.setRowState(6, 'createAndDeleted');  
    });

    //버튼을 클릭하면 9, 10행의 상태를 'updated'로 변경합니다.
    $("#btnSetRowStatesT").click(function () {
        dataProvider.setRowStates([8, 9], 'updated', true, true);
    });

    //버튼을 클릭하면 11, 12행의 상태를 'updated'로 변경합니다.
    $("#btnSetRowStatesF").click(function () {
        dataProvider.setRowStates([10, 11], 'updated', true, false);
    });

    //버튼을 클릭하면 10행의 상태를 가져옵니다.
    $("#btnGetRowState").click(function () {
        var state = dataProvider.getRowState(9);
        alert(state);
    });

    //버튼을 클릭하면 'deleted'상태인 행의 dataRow 목록을 가져옵니다.
    $("#btnGetStateRows").click(function () {
        var dataRows = dataProvider.getStateRows('deleted');
        alert(dataRows);
    });

    //버튼을 클릭하면 각 RowState 상태에 해당하는 dataRow들을 가져옵니다.
    $("#btnGetAllStateRows").click(function () {
        var states = dataProvider.getAllStateRows();
        alert(JSON.stringify(states));
    });

    //버튼을 클릭하면 행 상태가 사라집니다. 
    $("#btnClearRowStatesF").click(function () {
        dataProvider.clearRowStates(false, false);
    });

    //버튼을 클릭하면 행 상태가 사라집니다. 
    $("#btnClearRowStatesT").click(function () {
        dataProvider.clearRowStates(true, true);
    });


});   
 
</script>

HTML
1. <button type="button" class="btn btn-primary btn-xs" id="btnSetCallback">SetCallback</button> 버튼을 클릭하면 콜백 함수를 설정합니다. 화면에는 아무 변화가 없습니다. 

2. <button type="button" class="btn btn-primary btn-xs" id="btnSetRowStateCreated">setRowState(0, 'created')</button> 버튼을 클릭하면 첫 행의 RowState를 'created'로 변경합니다. (onRowStateChanged 호출)

3. 2행을 선택 후 `Ctrl`+`Insert`key를 입력하여 행을 추가합니다. 행 추가 후 data를 입력하고 편집까지 완료합니다. RowState를 'created'로 변경되는 것을 확인하세요. (onRowStateChanged 미호출, 신규 행이기때문에 행 상태가 변경 되는것이 아니기 때문입니다.)

4. <button type="button" class="btn btn-primary btn-xs" id="btnSetRowStateUpdated">setRowState(2, 'updated')</button> 버튼을 클릭하면 3 행의 RowState를 'updated'로 변경합니다. (onRowStateChanged 호출)

5. 4행을 선택후 데이터를 수정합니다. RowState를 'updated'로 변경되는 것을 확인하세요. (onRowStateChanged 호출)

6. <button type="button" class="btn btn-primary btn-xs" id="btnSetRowStateDeleted">setRowState(4, 'deleted')</button> 버튼을 클릭하면 5 행의 RowState를 'deleted'로 변경합니다. (onRowStateChanged 호출)

7. 6행을 선택후 `Ctrl`+`Del`key를 입력하여 행을 삭제합니다. RowState를 'deleted'로 변경되는 것을 확인하세요. (onRowStateChanged 호출)

8. <button type="button" class="btn btn-primary btn-xs" id="btnSetRowStateCreateAndDeleted">setRowState(6, 'createAndDeleted')</button> 버튼을 클릭하면 7 행의 RowState를 'createAndDeleted'로 변경합니다. (onRowStateChanged 호출)

9. 'created' 상태인 2행을 선택 후 `Ctrl`+`Del`key를 입력하여 행을 삭제합니다. RowState를 'createAndDeleted'로 변경되는 것을 확인하세요. (onRowStateChanged 호출, 3번에서는 호출되지 않았던 onRowStateChanged가 'created' 상태에서 변경되었기 때문에 이번에는 호출됩니다.)

10. <button type="button" class="btn btn-primary btn-xs" id="btnSetRowStatesT">setRowStates([8, 9], 'updated', true, true)</button> 버튼을 클릭하면 9, 10행의 상태를 'updated'로 변경합니다. (마지막 파라메터인 rowEvent가 true 일 경우 화면이 갱신되지 않는 버그가 있습니다. 스크롤 바를 움직이면 rowState가 정상적으로 표시됩니다., onRowStateChanged 호출되어야 하나 버그로 인해 호출되지 않습니다.)

11. <button type="button" class="btn btn-primary btn-xs" id="btnSetRowStatesF">setRowStates([10, 11], 'updated', true, false)</button> 버튼을 클릭하면 11, 12행의 상태를 'updated'로 변경합니다. (onRowStatesChanged 호출)

12. <button type="button" class="btn btn-primary btn-xs" id="btnGetRowState">getRowState(9)</button> 버튼을 클릭하면 10행의 상태를 가져옵니다.

13. <button type="button" class="btn btn-primary btn-xs" id="btnGetStateRows">getStateRows('deleted')</button> 버튼을 클릭하면 'deleted'상태인 행의 dataRow 목록을 가져옵니다.

14. <button type="button" class="btn btn-primary btn-xs" id="btnGetAllStateRows">getAllStateRows()</button> 버튼을 클릭하면 각 RowState 상태에 해당하는 dataRow들을 가져옵니다.

15. <button type="button" class="btn btn-primary btn-xs" id="btnClearRowStatesF">clearRowStates(false, false)</button> 버튼을 클릭하면 행 상태가 사라집니다. (onRowStatesCleared 호출, 첫번째 파라메터인 `deleteRows`가 false 이기 때문에 행 상태가 'deleted', 'createAndDeleted'인 행들이 삭제 되지 않고 RowState만 지워졌음을 확인하세요)

16. 몇 개의 행을 `Ctrl`+`Del`key를 입력하여 행들을 'deleted' 상태로 만들고, 몇 개의 행은 값을 수정하여 'updated' 상태로 만들어보세요.

17. <button type="button" class="btn btn-primary btn-xs" id="btnClearRowStatesT">clearRowStates(true, true)</button> 버튼을 클릭하면 행 상태가 사라집니다. ('deleted'였던 행들은 사라지고, 수정한 행 수 만큼 onRowStateChanged 호출)

<div id="realgrid" style="width: 100%; height: 250px;"></div>


데모 사이트


API 참조