[Nexacro N] Grid 셀 유효성 검사

Nexacro N Grid에서 oncelleditend 이벤트를 활용해 필수값·범위·형식 검사를 수행하고, setCellBackgroundColor로 오류 셀을 강조하는 패턴을 설명합니다.

· 6 min read · PALDYN Team

지난 글에서 Grid 셀 이벤트의 발생 순서와 이벤트 객체 활용법을 살펴봤습니다. 이번에는 실무에서 빠질 수 없는 Grid 셀 유효성 검사 패턴을 정리합니다. 어느 이벤트에서 검사할지, 실패 시 어떻게 사용자에게 알릴지까지 단계별로 설명합니다.

언제 검사할까?

Grid 셀 유효성 검사는 크게 두 시점에서 수행합니다.

시점이벤트특징
셀 편집 완료 시oncelleditend즉각적, 셀 단위 취소 가능
저장 버튼 클릭 시btnSave_onclickDataset 전체 순회, 종합 오류 목록

두 방식을 함께 쓰는 것이 일반적입니다. 셀 편집 시점에는 간단한 형식·범위 체크를 하고, 저장 시점에는 전체 행을 순회하며 필수값 누락이나 업무 규칙 위반을 최종 확인합니다.

Grid 셀 유효성 검사 흐름

oncelleditend에서 셀 단위 검사

편집이 끝나는 순간 e.newvalue를 검사하고, 실패하면 e.cancel = true로 편집을 원복합니다.

function grd_oncelleditend(obj, e) {
    var sColId = obj.getColumnId(e.col);
    var sVal   = e.newvalue;

    if (sColId == "EMAIL") {
        var reEmail = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        if (sVal && !reEmail.test(sVal)) {
            fn_markError(obj, e.row, e.col, "이메일 형식이 올바르지 않습니다.");
            e.cancel = true;
            return;
        }
    }

    if (sColId == "QTY") {
        var nQty = parseInt(sVal);
        if (isNaN(nQty) || nQty < 1 || nQty > 9999) {
            fn_markError(obj, e.row, e.col, "수량은 1 ~ 9999 사이로 입력하세요.");
            e.cancel = true;
            return;
        }
    }

    fn_clearError(obj, e.row, e.col);
}

Grid 셀 유효성 검사 코드 패턴

오류 표시 헬퍼 함수

오류를 표시하고 제거하는 작업은 공통 함수로 분리해 두면 여러 Grid에서 재사용할 수 있습니다.

function fn_markError(grd, nRow, nCol, sMsg) {
    grd.setCellBackgroundColor(nRow, nCol, "rgba(224,85,85,0.3)");
    grd.setCellForeColor(nRow, nCol, "#ff4444");
    stcErrMsg.set_text(sMsg);
    stcErrMsg.set_visible(true);
}

function fn_clearError(grd, nRow, nCol) {
    grd.setCellBackgroundColor(nRow, nCol, "");
    grd.setCellForeColor(nRow, nCol, "");
}

stcErrMsg는 화면 하단에 배치한 Static 컴포넌트로, 오류 메시지를 비블로킹 방식으로 표시합니다. alert()은 사용자 흐름을 끊기 때문에 입력이 많은 Grid에서는 이 패턴이 더 자연스럽습니다.

저장 시 전체 Grid 일괄 검사

저장 버튼 핸들러에서 Dataset을 순회하며 변경 행만 검사합니다.

function btnSave_onclick(obj, e) {
    var bValid = true;
    var nRowCnt = ds.rowcount;

    for (var i = 0; i < nRowCnt; i++) {
        var nStatus = ds.getRowType(i);
        // 추가/수정 행만 검사
        if (nStatus == Dataset.ROWTYPE_INSERT ||
            nStatus == Dataset.ROWTYPE_UPDATE) {

            var sName = ds.getColumn(i, "NAME");
            var sQty  = ds.getColumn(i, "QTY");

            if (!sName) {
                alert((i + 1) + "행: 이름은 필수 입력입니다.");
                grd.setCurrentRowIndex(i);
                bValid = false;
                break;
            }
            if (parseInt(sQty) < 1) {
                alert((i + 1) + "행: 수량은 1 이상이어야 합니다.");
                grd.setCurrentRowIndex(i);
                bValid = false;
                break;
            }
        }
    }

    if (bValid) {
        fn_save();
    }
}

오류가 발생한 행으로 Grid 포커스를 이동시켜(setCurrentRowIndex) 사용자가 바로 수정할 수 있게 합니다.

셀 배경색 일괄 초기화

저장 또는 조회 후 오류 표시를 모두 지우려면 Dataset의 모든 셀을 순회합니다.

function fn_clearAllErrors() {
    var nCols = grd.getColumnCount();
    var nRows = ds.rowcount;
    for (var r = 0; r < nRows; r++) {
        for (var c = 0; c < nCols; c++) {
            grd.setCellBackgroundColor(r, c, "");
            grd.setCellForeColor(r, c, "");
        }
    }
}

조회 버튼 클릭 이벤트 첫 줄에 이 함수를 호출하면, 이전 오류 표시가 새 데이터로 덮이지 않고 깔끔하게 초기화됩니다.

콤보·체크박스 셀 검사 주의사항

edittype="combo" 셀의 oncelleditend에서 e.newvaluecodecolumn 값(코드)입니다. datacolumn의 표시 텍스트가 아닙니다. 유효한 코드인지 확인하려면 bindingcodedataset에서 해당 코드를 찾아야 합니다.

function grd_oncelleditend(obj, e) {
    if (obj.getColumnId(e.col) == "DEPT_CD") {
        var nIdx = dsDept.findRow("DEPT_CD", e.newvalue);
        if (nIdx < 0) {
            fn_markError(obj, e.row, e.col, "유효하지 않은 부서 코드입니다.");
            e.cancel = true;
        }
    }
}

체크박스 셀은 클릭만으로 값이 토글되므로 oncelleditend가 발생하지 않습니다. 체크 상태 변화를 감지하려면 oncellchange를 사용합니다.

정규식을 이용한 형식 검사

대상정규식비고
숫자만/^\d+$/소수점 포함 시 /^\d+(\.\d+)?$/
날짜 YYYYMMDD/^\d{8}$/추가 범위 검사 별도 필요
사업자번호/^\d{3}-\d{2}-\d{5}$/하이픈 포함 형식
전화번호/^0\d{1,2}-\d{3,4}-\d{4}$/

정규식은 형식만 확인합니다. 날짜의 월/일이 실제로 유효한지(2월 30일 방지 등)는 별도 Date 파싱 검사를 추가합니다.


지난 글: Grid 셀 이벤트 완전 정복

다음 글: Grid 엑셀 단축키 설정


읽어주셔서 감사합니다. 😊