jqGrid 행 추가 및 데이터베이스 저장 구현

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 기반으로 정확히 매핑되어야 하며, 이는 서버 측 파라미터 바인딩 성공의 핵심입니다.

태그: jqGrid Spring MVC jQuery AJAX 폼 제출

7월 5일 23:14에 게시됨