들어가며

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

이론

그리드에서 값을 삭제하기 위해서는 기본적으로 editOptions의 속성중 deletable 속성값이 true 되어 있어야 삭제할 수 있습니다.

행 삭제 방법은 세가지 방법이 존재합니다.

  1. 그리드에서 입력장치로 삭제하기
  2. GridBase의 API를 이용하여 삭제하기
  3. DataProvider의 API를 이용하여 삭제하기

그리고 삭제 명령이 입력될때 즉시 행을 삭제하거나 RowStatedeleted or createAndDeleted로 바꾸는 방식을 사용할 수 있습니다.

우선 삭제와 관련된 옵션들을 알아본 다음 행을 삭제하는 방법에 대해 배워보겠습니다.

삭제와 관련된 옵션

삭제와 관련된 옵션은 다음 세 가지 입니다.

이 옵션들 중에서 삭제와 관련된 속성들을 살펴보도록 하겠습니다.

  • dataProviderOptions의 삭제 관련 속성
    • softDeleting : true이면 RowState만 deleted or createAndDeleted로 바꿉니다. false 인 경우 키보드 입력이나 API를 통한 삭제 입력시 바로 삭제됩니다.
    • deleteCreated : softDeleting이 true이면 기본적으로 RowState가 created 인 상태의 행을 삭제하면 createAndDeleted 로 변경됩니다. 그러나 이 값을 true 로 지정하면 바로 삭제됩니다.
    • dataProviderOptions 속성값 수정은 DataProvider.setOptions()함수를 이용합니다.
  • GridOptions의 삭제 관련 속성
    • hideDeletedRows : hideDeleteRows를 true로 지정하면 상태가 “deleted”이거나 “createAndDeleted”인 데이터행은 그리드에서 제외됩니다.
  • editOptions의 삭제 관련 속성
    • deletable : true 일 경우만 삭제 가능합니다.
    • deleteRowsConfirm : true면 사용자 삭제나 GridView.deleteSelection() 실행 시 삭제 여부를 묻는 대화 상자를 먼저 호출한다.
    • deleteRowsMessage : 내용을 입력하면 삭제 확인 대화 상자에 입력한 메시지가 표시된다. 지정하지 않으면 그리드 내부에 설정된 기본 메시지를 표시한다.
    • editOptions 속성값 수정은 GridBase.setEditOptions()함수를 이용합니다.

행 삭제 방법

1. 그리드에서 입력장치로 삭제하기

그리드에서 행을 삭제하려면 삭제하고 싶은행을 선택하고 바로 키보드로 Ctrl + Del key를 입력하면 삭제가 됩니다.

2. GridBase의 API를 이용하여 삭제하기

GridBase.deleteSelection(force) : 선택되어 있는 영역의 행을 삭제할 수 있습니다. force 속성에 true를 지정한 경우 위의 ‘삭제와 관련된 속성들’ 들에서 설명한 deleteRowsConfirm의 지정여부와 상관없이 바로 삭제됩니다.

3. DataProvider의 API를 이용하여 삭제하기

DataProvider에서 행 삭제하는 API는 두 가지가 있습니다.

콜백함수

행 삭제시 발행하는 콜백 함수는 아래와 같습니다.

하지만, 행 삭제시 이 콜백함수가 항상 발생하지는 않습니다. 위 이벤트들은 실제로 DataProvider에서 삭제될때 발생하며 위 ‘삭제와 관련된 속성들’ 중 softDeleting이 true 일 경우 실제적인 행삭제가 이루어지지 않고 행의 상태만 변경되는 것이기 때문에 이 삭제 콜백함수들은 호출되지 않습니다.

실습

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

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

     $("#btnSetCallback").click(function () {
         dataProvider.onRowDeleting = function (provider, row) {
             if (provider.getValue(row, "field3") == '이승환') {
                 setTimeout(function () { alert('이승환님은 삭제할 수 없습니다. onRowDeleting 발생') }, 0);
                 return false; // false를 리턴하면 삭제가 취소 됩니다.
             }
             alert("onRowDeleting 발생");
             return true;
         }
    
         dataProvider.onRowDeleted = function (provider, row) {
             alert("onRowDeleted 발생");
         }
    
         dataProvider.onRowsDeleted = function (provider, rows) {
             alert("onRowsDeleted 발생");
         }
     });
  2. 버튼을 클릭하면 선택한 행(들)이 삭제 됩니다.

     $("#btnDeleteSelectionF").click(function () {
         gridView.deleteSelection(false);   
     });
  3. 버튼을 클릭하면 선택한 행(들)이 삭제 됩니다.

     $("#btnDeleteSelectionT").click(function () {
         gridView.deleteSelection(true);   
     });
  4. 버튼을 클릭하면 네번째 행이 삭제 됩니다.

     $("#btnRemoveRow").click(function () {
         dataProvider.removeRow(3);
     });
  5. 버튼을 클릭하면 5, 6행이 삭제 됩니다.

     $("#btnRemoveRowsF").click(function () {
         dataProvider.removeRows([4, 5], false);
     });
  6. 버튼을 클릭하면 7, 8행이 삭제 됩니다.

     $("#btnRemoveRowsT").click(function () {
         dataProvider.removeRows([6, 7], true);
     });
  7. 버튼을 클릭하면 dataProvider 에 softDelting: true를 설정합니다.

     $("#btnSetSoftDeleting").click(function () {
         dataProvider.setOptions({softDeleting: true});
     });
  8. 버튼을 클릭하면 GridView 에 hideDeletedRows: true를 설정합니다.

    $("#btnSetHideDeletedRows").click(function () {
        gridView.setOptions({hideDeletedRows: true});
    });

실행화면

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

  2. 버튼을 클릭하면 선택한 행(들)이 삭제 됩니다. 마우스를 드래그하여 2~3행을 선택한 후 삭제해보세요. (Confirm창 표시, onRowsDeleted 1회 발생)

  3. 버튼을 클릭하면 선택한 행(들)이 삭제 됩니다. 1행을 선택한 후 삭제해보세요. (Confirm창 미표시, onRowDeleting, onRowDeleted 발생)

  4. 버튼을 클릭하면 네번째 행이 삭제 됩니다. (Confirm창 미표시, onRowDeleting, onRowDeleted 발생)

  5. 버튼을 클릭하면 5, 6행이 삭제 됩니다. (Confirm창 미표시, onRowsDeleted 1번 발생)

  6. 버튼을 클릭하면 7, 8행이 삭제 됩니다. (Confirm창 미표시, onRowDeleting, onRowDeleted 2번 발생)

  7. 이승환을 선택 후 Ctrl + Del key 를 입력하여 현재 선택된 행을 삭제해보세요. (Confirm창 표시, onRowDeleting - 삭제 안됨)

  8. 이승환이 아닌 사람 선택하고 Ctrl + Del key 를 입력하여 현재 선택된 행을 삭제해보세요. (Confirm창 표시, onRowDeleting, onRowDeleted 발생)

  9. 브라우져 새로고침 키 F5 key를 입력하여 페이지를 갱신한 후 10번부터 실행보세요.

  10. 버튼을 클릭하면 dataProvider 에 softDeleting: true를 설정합니다.

  11. 1번 버튼을 다시 클릭하여 콜백 함수를 설정합니다.

  12. 2~8번까지 다시 실행해보면서 어떤 차이가 있는지 확인해보세요.

  13. Confirm 창 표시되는 것만 동일하고 모든 콜백 함수는 호출되지 않았습니다. 이유는 softDeleting을 사용함으로서 rowState만 deleted상태로 바꾸는 것이지 실제적인 삭제가 이루어지는 것이 아니기 때문입니다. 이런 이유로 실제적인 삭제가 이루어질때 발생하는 콜백함수인 onRowDeleting이 발생하지 않았기 때문에 이전 7번에서는 삭제 되지 않았던 ‘이승환’의 rowState가 deleted로 변경되는 것을 확인할 수 있습니다.

  14. 버튼을 클릭하면 GridView 에 hideDeletedRows: true를 설정합니다. rowState가 deleted였던 행들이 그리드에서 사라집니다.

  15. Ctrl + Del key 를 입력하여 현재 선택된 행을 삭제해보세요. (hideDeletedRows: true이기 때문에 그리드에서 사라집니다. dataProvider에 rowState deleted 상태로 남아 있습니다.)

전체 소스코드

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: false
    })

    //버튼을 클릭하면 콜백 함수를 설정합니다.
    $("#btnSetCallback").click(function () {
        dataProvider.onRowDeleting = function (provider, row) {
            if (provider.getValue(row, "field3") == '이승환') {
                setTimeout(function () { alert('이승환님은 삭제할 수 없습니다. onRowDeleting 발생') }, 0);
                return false; // false를 리턴하면 삭제가 취소 됩니다.
            }
            alert("onRowDeleting 발생");
            return true;
        }

        dataProvider.onRowDeleted = function (provider, row) {
            alert("onRowDeleted 발생");
        }

        dataProvider.onRowsDeleted = function (provider, rows) {
            alert("onRowsDeleted 발생");
        }
    });

    //버튼을 클릭하면 선택한 행(들)이 삭제 됩니다. confirm 창 표시
    $("#btnDeleteSelectionF").click(function () {
        gridView.deleteSelection(false);   
    });

    //버튼을 클릭하면 선택한 행(들)이 삭제 됩니다. confirm 창 미표시
    $("#btnDeleteSelectionT").click(function () {
        gridView.deleteSelection(true);   
    });    

    //버튼을 클릭하면 네번째 행이 삭제 됩니다.
    $("#btnRemoveRow").click(function () {
        dataProvider.removeRow(3);
    });

    //버튼을 클릭하면 5, 6행이 삭제 됩니다. 개별행 이벤트 발생
    $("#btnRemoveRowsF").click(function () {
        dataProvider.removeRows([4, 5], false);
    });

    //버튼을 클릭하면 7, 8행이 삭제 됩니다. 이벤트 한번 발생
    $("#btnRemoveRowsT").click(function () {
        dataProvider.removeRows([6, 7], true);
    });

    //버튼을 클릭하면 dataProvider 에 softDelting: true를 설정합니다.
    $("#btnSetSoftDeleting").click(function () {
        dataProvider.setOptions({softDeleting: true});
    });

    // 버튼을 클릭하면 GridView 에 hideDeletedRows: true를 설정합니다.
    $("#btnSetHideDeletedRows").click(function () {
        gridView.setOptions({hideDeletedRows: 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="btnDeleteSelectionF">GridView.deleteSelection(false)</button> 버튼을 클릭하면 선택한 행(들)이 삭제 됩니다. 마우스를 드래그하여 2~3행을 선택한 후 삭제해보세요. (Confirm창 표시, onRowsDeleted 1회 발생)

3. <button type="button" class="btn btn-primary btn-xs" id="btnDeleteSelectionT">GridView.deleteSelection(true)</button> 버튼을 클릭하면 선택한 행(들)이 삭제 됩니다. 1행을 선택한 후 삭제해보세요. (Confirm창 미표시, onRowDeleting, onRowDeleted 발생)

4. <button type="button" class="btn btn-primary btn-xs" id="btnRemoveRow">dataProvider.removeRow(3)</button> 버튼을 클릭하면 네번째 행이 삭제 됩니다. (Confirm창 미표시, onRowDeleting, onRowDeleted 발생)

5. <button type="button" class="btn btn-primary btn-xs" id="btnRemoveRowsF">dataProvider.removeRows([4,5], false)</button> 버튼을 클릭하면 5, 6행이 삭제 됩니다. (Confirm창 미표시, onRowsDeleted 1번 발생)

6. <button type="button" class="btn btn-primary btn-xs" id="btnRemoveRowsT">dataProvider.removeRows([6,7], false)</button> 버튼을 클릭하면 7, 8행이 삭제 됩니다. (Confirm창 미표시, onRowDeleting, onRowDeleted 2번 발생)

7. 이승환을 선택 후 `Ctrl` + `Del` key 를 입력하여 현재 선택된 행을 삭제해보세요. (Confirm창 표시, onRowDeleting - 삭제 안됨)

8. 이승환이 아닌 사람 선택하고 `Ctrl` + `Del` key 를 입력하여 현재 선택된 행을 삭제해보세요. (Confirm창 표시, onRowDeleting, onRowDeleted 발생)

9. 브라우져 새로고침 키 `F5` key를 입력하여 페이지를 갱신한 후 10번부터 실행보세요. 

10. <button type="button" class="btn btn-primary btn-xs" id="btnSetSoftDeleting">softDeleting: true</button>버튼을 클릭하면 dataProvider 에 softDeleting: true를 설정합니다.

11. 1번 버튼을 다시 클릭하여 콜백 함수를 설정합니다.

12. 2~8번까지 다시 실행해보면서 어떤 차이가 있는지 확인해보세요.
 
13. Confirm 창 표시되는 것만 동일하고 모든 콜백 함수는 호출되지 않았습니다. 이유는 softDeleting을 사용함으로서 rowState만 `deleted`상태로 바꾸는 것이지 실제적인 삭제가 이루어지는 것이 아니기 때문입니다. 이런 이유로 실제적인 삭제가 이루어질때 발생하는 콜백함수인 onRowDeleting이 발생하지 않았기 때문에 이전 7번에서는 삭제 되지 않았던 '이승환'의 rowState가 `deleted`로 변경되는 것을 확인할 수 있습니다.

14. <button type="button" class="btn btn-primary btn-xs" id="btnSetHideDeletedRows">hideDeletedRows: true</button> 버튼을 클릭하면 GridView 에 hideDeletedRows: true를 설정합니다. rowState가 `deleted`였던 행들이 그리드에서 사라집니다., Grid에서만 사라진 것이지 dataProvider에서 실제로 삭제된 것이 아닙니다.

15. `Ctrl` + `Del` key 를 입력하여 현재 선택된 행을 삭제해보세요. (rowState가 `deleted`로 바뀌는 것이 아니고 바로 그리드에서 사라집니다. dataProvider에는 삭제되지 않고 남아 있습니다.)

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


데모 사이트


API 참조