jqGrid를 사용하여 동적으로 행을 추가하고, 입력된 폼 데이터를 서버로 전송하여 데이터베이스에 저장하는 방법을 설명합니다. 전체 그리드는 HTML 폼 안에 포함되며, 제출 시 직렬화된 입력 값들이 Spring 기반 백엔드로 전달됩니다.
HTML 폼 구조
jqGrid는 <form> 태그 내부에 위치하며, 폼 제출 시 모든 입력 요소가 함께 전송될 수 있도록 구성합니다.
<form id="gridForm" method="post">
<table id="dynamicGrid"></table>
<div id="gridPager"></div>
<div class="form-actions">
<button type="submit" class="btn primary">저장</button>
<button type="button" class="btn" onclick="goBack()">취소</button>
</div>
</form>
JavaScript: jqGrid 초기화 및 동적 행 삽입
그리드는 JSON 기반 데이터 로딩을 지원하며, 컬럼 모델은 각 필드의 이름, 너비, 정렬 등을 정의합니다. 입력 필드와 셀렉트 박스는 addRowData를 통해 동적으로 삽입됩니다.
$("#dynamicGrid").jqGrid({
datatype: "local",
colModel: [
{ name: "line", index: "line", width: 90, align: "left", title: false },
{ name: "section", index: "section", width: 90, align: "left" },
{ name: "mileage", index: "mileage", width: 100, align: "left" },
{ name: "workshop", index: "workshop", width: 110, sortable: false },
{ name: "team", index: "team", width: 100, align: "left" },
{ name: "person", index: "person", width: 100, align: "left" },
{ name: "inspector", index: "inspector", width: 120, editable: true,
edittype: "text", editoptions: { name: "inspector" } },
{ name: "rainfall", index: "rainfall", width: 100, editable: true,
edittype: "text", editoptions: { name: "rainfall", placeholder: "강우량 입력" } },
{ name: "alertType", index: "alertType", width: 90, editable: true,
edittype: "select",
editoptions: {
name: "alertType",
value: "patrol:순찰;speed_limit:속도제한;block:봉쇄"
}
},
{ name: "checkRule", index: "checkRule", width: 130, editable: true,
edittype: "text", editoptions: { name: "checkRule" } },
{ name: "specialReq", index: "specialReq", width: 130, editable: true },
{ name: "notes", index: "notes", width: 130, editable: true },
{ name: "remarks", index: "remarks", width: 100, editable: true }
],
viewrecords: true,
rownumbers: false,
gridview: true,
autoencode: true,
hidegrid: false,
height: 'auto',
shrinkToFit: true,
rowNum: 10000 // 무제한 행 (페이징 비활성)
});
// 새로운 빈 행 추가 함수
function appendEmptyRow() {
const newRowId = "new_row_" + Math.floor(Math.random() * 10000);
const emptyData = {
line: "",
section: "",
mileage: "",
inspector: '<input type="text" name="inspector" placeholder="점검자 입력"/>',
rainfall: '<input type="text" name="rainfall" placeholder="강우량 입력"/>',
alertType: '<select name="alertType">' +
'<option value="patrol">순찰</option>' +
'<option value="speed_limit">속도제한</option>' +
'<option value="block">봉쇄</option>' +
'</select>',
checkRule: '<input type="text" name="checkRule" placeholder="점검 조건 입력"/>',
specialReq: '<input type="text" name="specialReq" placeholder="전문 점검 요구사항"/>',
notes: '<input type="text" name="notes" placeholder="참고사항"/>'
};
$("#dynamicGrid").jqGrid("addRowData", newRowId, emptyData, "first");
}
폼 제출 처리 (AJAX)
jQuery Validation 플러그인을 사용해 폼 제출을 가로채고, serialize()를 통해 모든 입력값을 쿼리 문자열로 변환하여 서버로 전송합니다.
$("#gridForm").validate({
submitHandler: function(form) {
const formData = $(form).serialize();
$.ajax({
url: "/rain-inspection/save",
type: "POST",
data: formData,
dataType: "json",
async: false,
success: function(response) {
if (response.success) {
alert("정상적으로 저장되었습니다.");
window.location.href = "/rain-inspection/list";
} else {
alert("저장 실패: " + response.message);
}
},
error: function() {
alert("서버 요청 중 오류 발생.");
}
});
}
});
백엔드 Java 컨트롤러 (Spring MVC)
클라이언트에서 전송된 배열 형태의 파라미터는 @RequestParam으로 배열로 바인딩됩니다. 각 필드명은 입력 요소의 name 속성과 일치해야 합니다.
@PostMapping("/rain-inspection/save")
@ResponseBody
@RequiresPermissions("inspection:create")
public Map<String, Object> saveInspectionRecords(
@RequestParam("inspector") String[] inspectors,
@RequestParam("rainfall") String[] rainfalls,
@RequestParam("alertType") String[] alertTypes,
@RequestParam("checkRule") String[] checkRules,
@RequestParam("specialReq") String[] specialReqs,
@RequestParam(value = "notes", required = false) String[] notesArr) {
List<InspectionRecord> records = new ArrayList<>();
int length = inspectors.length;
for (int i = 0; i < length; i++) {
InspectionRecord record = new InspectionRecord();
record.setInspector(inspectors[i]);
record.setRainfall(parseDoubleSafe(rainfalls[i]));
record.setAlertLevel(alertTypes[i]);
record.setCheckRequirement(checkRules[i]);
record.setSpecialRequirement(safeGet(notesArr, i));
record.setCreateTime(new Date());
records.add(record);
}
inspectionService.saveAll(records);
Map<String, Object> result = new HashMap<>();
result.put("success", true);
result.put("message", "모든 데이터가 저장되었습니다.");
return result;
}
private Double parseDoubleSafe(String val) {
try { return val != null && !val.trim().isEmpty() ? Double.parseDouble(val) : 0.0; }
catch (NumberFormatException e) { return 0.0; }
}
private String safeGet(String[] arr, int i) {
return arr != null && i < arr.length ? arr[i] : "";
}
addRowData 메서드 요약
jqGrid의 addRowData는 그리드에 새 행을 삽입하는 핵심 메서드입니다.
$("#dynamicGrid").jqGrid("addRowData", rowId, rowData, position);
- rowId: 고유 식별자 (문자열 또는 숫자)
- rowData: 컬럼
name을 키로 하는 데이터 객체 - position:
"first","last","before","after"
동적 입력 필드를 포함한 행은 폼 제출 시 name 기반으로 정확히 매핑되어야 하며, 이는 서버 측 파라미터 바인딩 성공의 핵심입니다.