들어가며

[A15 강좌],[A16 강좌]에서는 로우 그룹핑(row grouping)하는 방법에 대한 기본적인 내용을, [B2-2 Row Grouping] 강좌에서는 로우 그룹핑(row grouping) 옵션에 대한 내용을 배웠습니다.

이번 강좌에서는 로우 그룹핑 상태에서 셀을 병합(merged)하는 방법과 그와 관련된 몇가지 옵션들에 대해 배워보겠습니다.

이론

로우 그룹핑 상태에서 셀을 병합하는 것을 병합된 로우 그룹핑(Merged row grouping)이라고 표현하며 [B2-2 Row Grouping]강좌에서 배웠던 로우 그룹 옵션(RowGroupOptions)중 병합셀과 관련된 몇가지 속성들을 통해 이 기능을 구현 할 수 있습니다.

로우 그룹 옵션(RowGroupOptions)중 Merged row grouping과 관련된 속성은 아래와 같습니다.

  • mergeMode
    • 행 그룹핑시 그룹된 컬럼의 merge표현 여부를 지정합니다.
    • 기본값은 false이며 true로 설정하면 그룹핑된 셀들이 병합 표시 됩니다.
  • expandedAdornments
    • 그룹이 펼쳐진 상태일 때 그룹의 header, footer의 표시 여부를 지정할 수 있습니다.
    • 설정 값은 RowGroupAdornments 타입이며 both, header, footer, none이 있습니다.
    • both로 설정하면 펼쳤을 때 header와 footer가 모두 보여 집니다.
    • header로 설정하면 펼쳤을 때 header만 보여 집니다.
    • footer로 설정하면 펼쳤을 때 footer만 보여 집니다.
    • none으로 설정하면 펼쳤을 때 header와 footer모두 보이지 않게 됩니다.
  • collapsedAdornments
    • 그룹이 접혀진 상태일때 그룹의 header, footer의 표시여부를 지정할 수 있습니다.
    • 설정 값은 RowGroupAdornments 타입이며 both, header, footer가 있습니다.
    • both로 설정하면 접혔을 때 header와 footer가 모두 보여 집니다.
    • header로 설정하면 접혔을 때 header만 보여 집니다.
    • footer로 설정하면 접혔을 때 footer만 보여 집니다.
    • collapsedAdornments인 경우 RowGroupAdornments.NONE은 구현되지 않습니다.
  • mergeExpander
    • mergeMode가 true인 경우 데이터 셀에 expander(그룹을 접거나 펼칠 수 있는 버튼)표시여부를 정할 수 있습니다.
    • true로 설정하면 expander가 표시됩니다.
    • false로 설정하면 expander가 표시되지 않습니다.

RowGroupOptions을 설정하기 위해서는 gridView.setRowGroup()함수를 사용하며 RowGroupOptions을 인자로 넘겨줍니다.

행 분리 방지

RealGrid는 Merged Row Grouping상태에서 셀을 편집할 때 편집중인 행을 구분하기 위해 위의 그림과 같이 일시적으로 행이 분리되는 기능이 있습니다. 하지만, 병합된 셀의 편집이 필요없거나 편집상태를 확인할 필요가 없을 때에는 이 기능을 사용하지 않도록 설정을 변경 할 수 있습니다.

이 기능은 DisplayOptionseditItemMerging속성으로 지정할 수 있습니다. 기본값을 false이며 편집시 행이 분리되어 보입니다. true로 설정하면 병합된 상태에서 편집시 아래 그림과 같이 행이 분리되어 보이지 않게 됩니다.

이 기능은 1.0.13버전 이상에서 정상적으로 동작 합니다.

아래 실습을 통하여 병합된 로우 그룹을 설정하는 방법을 알아보겠습니다.

실습

실습에서는 expanded와 collapsed의 속성을 사용해보면서 차이점을 살펴보도록 하겠습니다.

  1. 실습을 위한 그룹에 관련된 설명은 [A15 강좌], [A16 강좌]와 동일합니다.

  2. 그룹시 초기에 보여지는 설정을 위해 아래 코드를 추가합니다. mergeMode옵션을 true로 설정하고 접었을 때와 펼쳤을 때 모두 footer만 보이도록 collapsedAdornments, expandedAdornments를 각각 footer로 설정합니다.

      gridView.setOptions({
         rowGroup: {
             mergeMode: true,
             expandedAdornments: "footer",
             collapsedAdornments: "footer"
         }
     });
  3. 버튼을 클릭하면 header, footer만 보이거나 또는 둘다 보이지 않도록 expandedAdornments를 header, footer, none으로 설정하는 코드를 아래와 같이 작성 합니다.

     $("#btnExpandedHeader").on("click", function(){
         gridView.setRowGroup({
             expandedAdornments: "header"
         });
     });
        
     $("#btnExpandedFooter").on("click", function(){
         gridView.setRowGroup({
             expandedAdornments: "footer"
         });
     });
        
     $("#btnExpandedNone").on("click", function(){
         gridView.setRowGroup({
             expandedAdornments: "none"
         });
     });
  4. 버튼을 클릭하면 그룹이 접혀진 상태일 때 header, footer영역이 모두 보이도록 collapsedAdornments속성을 both로 설정하는 코드를 작성합니다.

     //rowGroup이 펼쳐지지 않은 상태일 때
     $("#btnCollapsedBoth").on("click", function(){
         gridView.setRowGroup({
             collapsedAdornments: "both"
         });
     });
  5. 버튼을 클릭하면 병합된 데이터 셀에 Expander표시가 보여지도록 하고 다시 한번 클릭시 감추어 지도록 하기 위해 아래 코드와 같이 getRowGroup()함수를 이용해 가져온 현재 상태를 반전하는 코드를 아래와 같이 작성합니다.

     $("#btnExpander").on("click", function(){
         var rowgroupoptions = gridView.getRowGroup();
            
         gridView.setRowGroup({
             mergeExpander: !rowgroupoptions.mergeExpander;
         });
     });
  6. 버튼을 클릭하면 행 분리 기능을 사용하지 않도록 DisplayOptions.editItemMerging 속성을 true로 설정합니다.

     $("#btnSetEditItemMerging").on("click", function(){
         gridView.setDisplayOptions({
             editItemMerging: true
         });
     });

실행화면

  1. 버튼을 클릭하여 그룹을 설정합니다. 직업컬럼의 데이터 셀이 병합이 되었는지 확인합니다.

  2. 버튼을 클릭하여 expandedAdornments의 값을 header로 변경합니다. 그룹이 펼쳐진 상태일 때 header가 보이는지 확인합니다.

  3. 버튼 클릭시 expandedAdornments의 값을 footer로 변경합니다. header가 보이는지 확인합니다.

  4. 버튼 클릭시 expandedAdornments의 값을 none로 변경합니다. header와 foorter가 사라졌는지 확인합니다.

  5. 버튼 클릭시 collapsedAdornments의 값을 both로 변경합니다. 그룹이 접혀진 상태일 때 header와 foorter가 둘다 보이는지 확인합니다.

  6. 버튼 클릭시 병합된 자리의 버튼을 숨길 수 있습니다. 병합된 데이터 셀의 버튼이 사라졌는지 확인합니다. 다시 한번 클릭시 Expander가 다시 나타나게 됩니다.

  7. 특정행의 국어컬럼을 편집해 봅니다. 해당 행의 병합된 직업컬럼이 분리되어 보이는 것을 확인 합니다. 버튼을 클릭한 다음 특정행의 국어컬럼을 편집해 봅니다. 해당 행의 직업컬럼이 분리되지 않는 것을 확인 합니다.

전체 소스코드

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",
            dataType: "number"
        },
        {
            fieldName: "field5",
            dataType: "number"
        },
        {
            fieldName: "field6",
            dataType: "number"
        },
        {
            fieldName: "field7",
            dataType: "number"
        },
        {
            fieldName: "field8",
            dataType: "number"
        },
        {
            fieldName: "field9",
            dataType: "number"
        },
        {
            fieldName: "field10",
            dataType: "number"
        }
    ];
    //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: "이름"
            },
            footer: {
                text: "평균=>",
                groupText: "평균=>"
            },
            width: 80
        },
        {
            name: "col4",
            fieldName: "field4",
            header : {
                text: "국어"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            width: 80
        },
        {
            name: "col5",
            fieldName: "field5",
            header : {
                text: "수학"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            width: 80
        },
        {
            name: "col6",
            fieldName: "field6",
            header : {
                text: "민법"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            width: 80
        },
        {
            name: "col7",
            fieldName: "field7",
            header : {
                text: "한국사"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            width: 80
        },
        {
            name: "col8",
            fieldName: "field8",
            header : {
                text: "영어"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            width: 80
        },
        {
            name: "col9",
            fieldName: "field9",
            header : {
                text: "과학"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            width: 80
        },
        {
            name: "col10",
            fieldName: "field10",
            header : {
                text: "사회"
            },
            footer: {
            	styles: {
            	    textAlignment: "near",
            	    numberFormat: "0"
            	},
            	text: "평균",
            	expression: "avg",
            	groupExpression: "avg"
            },
            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);
    
    //rowGroup초기 설정
    gridView.setOptions({
        rowGroup: {
            mergeMode: true,
            expandedAdornments: "footer",
            collapsedAdornments: "footer"
        }
    });
    
    //직업컬럼 단일그룹
    $("#btnField1Group").on("click", function(){
        gridView.groupBy(["field1"]);
    });
    
    //rowGroup이 펼쳐진 상태일 때
    $("#btnExpandedHeader").on("click", function(){
        gridView.setRowGroup({
            expandedAdornments: "header"
        });
    });
    
    $("#btnExpandedFooter").on("click", function(){
        gridView.setRowGroup({
            expandedAdornments: "footer"
        });
    });
    
    $("#btnExpandedNone").on("click", function(){
        gridView.setRowGroup({
            expandedAdornments: "none"
        });
    });
    
    //rowGroup이 펼쳐지지 않은 상태일 때
    $("#btnCollapsedBoth").on("click", function(){
        gridView.setRowGroup({
            collapsedAdornments: "both"
        });
    });
    
    //Expander 보이기/숨기기 토글
    $("#btnExpander").on("click", function(){
        var rowgroupoptions = gridView.getRowGroup();

        gridView.setRowGroup({
            mergeExpander: !rowgroupoptions.mergeExpander
        });
    });

    $("#btnSetEditItemMerging").on("click", function(){
        gridView.setDisplayOptions({
            editItemMerging: true
        });
    });
    
});   

</script>

HTML

1. <button type="button" id="btnField1Group">작업컬럼으로 그룹잡기</button> 버튼을 클릭하여 그룹을 설정합니다. 직업컬럼의 데이터 셀이 병합이 되었는지 확인합니다.

2. <button type="button" id="btnExpandedHeader">expandedAdornments: "header"</button> 버튼을 클릭하여 expandedAdornments의 값을 "header"로 변경합니다. Rowgroup이 펼쳐진 상태일 때 rowGroup.header가 보이는지 확인합니다.

3. <button type="button" id="btnExpandedFooter">expandedAdornments: "footer"</button>버튼 클릭시  expandedAdornments의 값을 "footer"로 변경합니다. rowGroup.header가 보이는지 확인합니다.

4. <button type="button" id="btnExpandedNone">expandedAdornments: "none"</button>버튼 클릭시 expandedAdornments의 값을 "none"로 변경합니다. rowGroup.header와 rowGroup.foorter가 사라졌는지 확인합니다.

5. <button type="button" id="btnCollapsedBoth">collapsedAdornments: "both"</button>클릭시 collapsedAdornments의 값을 "both"로 변경합니다. Rowgroup이 펼쳐지지 않은 상태일 때 rowGroup.header와 rowGroup.foorter가 둘다 보이는지 확인합니다.

6. <button type="button" id="btnExpander">Expander감추기/보이기</button>버튼 클릭시 병합된 셀에 expander표시를 없앨 수 있습니다. 병합된 데이터 셀의 expander표시가 사라졌는지 확인합니다.

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


데모 사이트


API 참조