개발 메모장

[jQuery] jqGrid rowspan 셀 병합 본문

Java Script

[jQuery] jqGrid rowspan 셀 병합

yyyyMMdd 2024. 6. 25. 16:38
728x90

#. 여타 그리드의 경우 셀 병합 기능이 기본적으로 제공되나 jqGrid의 경우 무료로 사용하기에 부족한 기능들이 많은 편입니다.

 

#. 다른 행 데이터 내 동일한 Key로 묶인 경우 병합하여 보여주는 기능을 요청하여 남겨보도록 하겠습니다.


  • 우선 요청사항을 정확히 살펴보도록 하겠습니다.

  • 아래 요청사항은 기본적으로 TestNo이라는 값이 동일한 행에 대해 적용해달라는 것이 기본이였습니다.

1. 첫 행의 Key가 N이면서 나머지 행도 N인 경우 첫 행을 제외한 나머지 행의 특정 데이터를 보여주지 않을 것

2. 첫 행 Key가 N이고 나머지 행 중 Y라는 Key를 가진 경우 첫 행의 특정 데이터를 보여주지 않을 것

3. 첫 행 Key가 Y이면서 나머지 행도 모두 Y인 경우 모두 보여줄 것

 

4. 동일한 TestNo일 경우 data7과 data8을 rowspan 할 것


  • 데이터는 DB에서 가져와 grid에 뿌려주고 화면에서만 병합되어 보일 수 있도록
    호출 후 실행되는 setGridParam 내 loadComplete 옵션에 작성하였습니다.

  • 아래를 보면 알 수 있듯이 최초 colModel에 작성한 name의 값이 grid_와 함께 aria-describedby의 값에 들어가 있습니다.

  • 또한 row 하나당 ID의 숫자 값이 1씩 증가합니다.

  • 이를 이용해 처리하도록 하겠습니다.


#. 작성 코드

 

  • getDataIDs를 이용해 해당 행을 담고 getCell을 이용해 특정 행의 특정 열의 데이터를 가져옵니다.

  • currTestNo와 prevTestNo을 비교하여 동일하면 Key에 따른 분기처리를 합니다.

  • 셀 병합, 데이터 가리기, 데이터 삭제 처리는 별도 함수로 처리하였습니다.

  • 또한 데이터를 병합한 셀을 클릭할 시 multiSelect 할 수 없도록 막고 한번에 하나의 행만 선택할 수 있도록 처리하였습니다.

$("#grid").setGridParam({
            url: "/test.do?" + $('#test').serialize(), // data와 함께 전달
            datatype: "json"
            ,loadComplete: function(data) {
// 동일 전표번호에 대한 중복 셀 데이터 제거
            	var ids = $('#grid').getDataIDs();
            	var prevTestNo = null; 		// currTestNo와 비교할 변수
            	var prevKey = null;		// currKey와 비교할 변수
            	var rowspan = 1;		// 행 병합을 위한 변수
            	var startRowId = null;		// 병합 및 데이터 삭제 시 시작 row의 id 번호
            	
            	for(var i = 0; i < ids.length; i++) {
            		var currTestNo = $('#grid').getCell(ids[i], 'TestNo');	 // prevTestNo와 비교할 변수
            		var currKey = $('#grid').getCell(ids[i], 'Key');	// prevKey와 비교할 변수
            		
            		if(prevTestNo === currTestNo) {
	           		if(prevKey === 'N' && currKey === 'Y') {
					// 데이터를 그리드에서 보이지 않게 처리
	           			clearRowData(ids[i - 1], false);
	           		} else if(prevKey === 'Y' && currKey === 'Y') {
	           			
	           		} else {
	           			clearRowData(ids[i], true);
	           		}
				// TestNo이 중복인 경우 특정 데이터를 삭제
            			hideDuplicateCells(ids[i]);
            			rowspan++;
	           		if(!startRowId) {
	           			startRowId = ids[i-1];
	           		}
            		} else {
            			if(rowspan > 1 && startRowId) {
					// 병합 처리 함수
            				mergeCells(startRowId, rowspan);
            			}
            			
				// 변수 초기화
            			prevTestNo = currTestNo;
            			prevKey = currKey;
            			rowspan = 1;
            			startRowId = null;
            		}
            	}
            	
            	if(rowspan > 1 && startRowId) {
       			mergeCells(startRowId, rowspan);
            	}
            	
            	// 데이터를 보이지 않게 한 행의 체크박스 클릭 막기
		$('#grid').find('.no-multiselect .cbox').prop('disabled', true).off('click');

            	// 멀티셀렉트 - 이전 선택 해제 후 선택할 수 있게 하기
		var grid = $("#grid");
		var lastSelectedRow
		grid.off("jqGridBeforeSelectRow").on("jqGridBeforeSelectRow", function (e, rowid, isSelected) {
			if (isSelected && rowid !== lastSelectedRow) {
				grid.jqGrid("resetSelection");
				lastSelectedRow = rowid;
			}
			return true;
		});
	}
}).trigger("reloadGrid");
728x90

  • 사용 함수 코드
// 데이터 삭제하기
function clearRowData(rowId, clearTestNo) {
	// tr과 td 모두 적용
	$('#grid').find('tr[id=' + rowId + ']').addClass('no-multiselect');
	$('#grid').find('tr[id=' + rowId + ']').find('td').addClass('no-multiselect');

	// 특정 조건일 때만 데이터 삭제
	if (clearTestNo) {
		$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_TestNo]").text('');
	}
	// 특정 colModel 값의 데이터 삭제
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_Key]").text('');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data1]").text('');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data2]").text('');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data3]").text('');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data4]").text('');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data5]").text('');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data6]").text('');
}
		
// 특정 데이터 개체를 아예 없애기
function hideDuplicateCells(rowId) {
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data7]").css('display', 'none');
	$("#grid").find("tr[id=" + rowId + "] td[aria-describedby=grid_data8]").css('display', 'none');
}

// 특정 데이터의 열 병합
function mergeCells(startRowId, rowspan) {
	var data7Cell = $("#grid").find("tr[id=" + startRowId + "] td[aria-describedby=grid_data7]");
	data7Cell.attr('rowspan', rowspan);
	for (var i = 1; i < rowspan; i++) {
		$("#grid").find("tr[id=" + (parseInt(startRowId) + i) + "] td[aria-describedby=grid_data7]").remove();
	}

	var data8Cell = $("#grid").find("tr[id=" + startRowId + "] td[aria-describedby=grid_data8]");
	data8Cell.attr('rowspan', rowspan);
	for (var i = 1; i < rowspan; i++) {
		$("#grid").find("tr[id=" + (parseInt(startRowId) + i) + "] td[aria-describedby=grid_data8]").remove();
	}
}

#. 적용 결과

 

1. 동일한 TestNo의 첫 행 Key가 N 또는 Y이면서 다음 행은 N인 경우 데이터를 안 보이게 설정하였습니다.


2. 동일한 TestNo의 첫 행 Key가 Y이면서 다음 행도 Y인 경우엔 데이터를 전부 보이게 설정하였습니다.


3. 동일한 TestNo의 첫 행 Key가 N이고 다음 행이 Y인 경우 첫 행을 보이지 않도록 설정하였습니다.


  • 한가지 단점이라 하면 2, 3번과 같이 하단 행의 data7과 data8을 이용해 처리하려할 때 발생합니다.

  • 그리드에 나타나는 모습은 data7과 data8값이 1, 2 라인에 모두 있는 것으로 보이나 실은 1 라인에만 있는 값입니다.

  • getRowData를 이용해 클릭된 데이터를 가져오고 colModel name을 입력하여 가져오는 방법으론 데이터가 맞지 않을 수 있으니 이에 대한 로직을 추가적으로 개발해야 합니다.

 

 

======================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!

======================================

728x90