개발노트/jqGrid

[jqGrid] 기본 예제 (게시판 만들기)

dev-mylee 2025. 1. 23. 12:12

프로젝트하면서 제일 많이 만드는 게시판 예제로 정리해봄.

기본적인 CRUD랑 검색, 정렬 다 들어있음.

 

 

1. HTML 구조

<!-- 검색 영역 -->
<div class="search-area">
    <form id="searchForm">
        <input type="text" id="searchTitle" placeholder="제목">
        <input type="text" id="searchWriter" placeholder="작성자">
        <button type="button" id="btnSearch">검색</button>
        <button type="button" id="btnWrite">글쓰기</button>
    </form>
</div>

<!-- 그리드 영역 -->
<table id="boardGrid"></table>
<div id="pager"></div>

 

 

 

2. jqGrid 초기화 및 설정

$(document).ready(function() {
    initGrid();
    initEvents();
});

function initGrid() {
    $("#boardGrid").jqGrid({
        url: '/api/board/list',
        datatype: 'json',
        mtype: 'POST',
        colNames: ['번호', '제목', '작성자', '작성일', '조회수', 'boardId'],
        colModel: [
            {name: 'rowNum', index: 'rowNum', width: 80, align: 'center', sortable: false},
            {
                name: 'title', 
                index: 'title', 
                width: 300, 
                align: 'left',
                formatter: function(cellvalue, options, rowObject) {
                    // 제목 클릭하면 상세페이지로
                    var link = '<a href="javascript:void(0);" onclick="goDetail(' + rowObject.boardId + ')">';
                    
                    // 제목에 댓글수, 첨부파일 아이콘 추가
                    if(rowObject.replyCount > 0) {
                        cellvalue += ' <span class="reply-cnt">[' + rowObject.replyCount + ']</span>';
                    }
                    if(rowObject.hasAttachment === 'Y') {
                        cellvalue += ' <img src="/images/icon-file.gif">';
                    }
                    
                    return link + cellvalue + '</a>';
                }
            },
            {name: 'writer', index: 'writer', width: 100, align: 'center'},
            {
                name: 'regDate', 
                index: 'regDate', 
                width: 100, 
                align: 'center',
                formatter: 'date', 
                formatoptions: {srcformat: 'Y-m-d H:i:s', newformat: 'Y-m-d'}
            },
            {name: 'viewCount', index: 'viewCount', width: 80, align: 'center'},
            {name: 'boardId', index: 'boardId', hidden: true}
        ],
        height: 500,
        autowidth: true,
        rowNum: 10,
        rowList: [10, 20, 30],
        pager: '#pager',
        sortname: 'regDate',
        sortorder: 'desc',
        viewrecords: true,
        rownumbers: false,
        loadComplete: function(data) {
            // 데이터 없을 때 메시지 처리
            if(data.records === 0) {
                showNoDataMessage($(this));
            }
        }
    });
}

 

 

 

3. 이벤트 처리

function initEvents() {
    // 검색 버튼 클릭
    $("#btnSearch").on("click", function() {
        searchBoard();
    });
    
    // 글쓰기 버튼 클릭
    $("#btnWrite").on("click", function() {
        location.href = "/board/write";
    });
}

function searchBoard() {
    var searchParam = {
        title: $("#searchTitle").val(),
        writer: $("#searchWriter").val()
    };
    
    $("#boardGrid").jqGrid('setGridParam', {
        postData: searchParam,
        page: 1
    }).trigger("reloadGrid");
}

// 상세페이지 이동
function goDetail(boardId) {
    location.href = "/board/detail/" + boardId;
}

// 데이터 없을 때 메시지 표시
function showNoDataMessage($grid) {
    var colModel = $grid.jqGrid('getGridParam', 'colModel');
    var colspan = colModel.length;
    
    $grid.jqGrid('clearGridData');
    
    var $message = $("<tr><td colspan='" + colspan + "' class='no-data'>데이터가 없습니다.</td></tr>");
    $grid.find("tbody").append($message);
}

 

 

 

4. CSS 스타일링

/* 검색 영역 */
.search-area {
    margin-bottom: 20px;
    padding: 15px;
    background: #f5f5f5;
    border: 1px solid #ddd;
}

/* 그리드 커스텀 스타일 */
.ui-jqgrid {
    border: 1px solid #ddd;
    font-size: 14px;
}

.ui-jqgrid .ui-jqgrid-htable th {
    background: #f8f9fa;
    padding: 8px;
}

.ui-jqgrid tr.jqgrow td {
    padding: 8px;
}

/* 댓글수 스타일 */
.reply-cnt {
    color: #ff6b6b;
    font-weight: bold;
}

/* No Data 메시지 */
td.no-data {
    text-align: center;
    padding: 50px 0;
    color: #666;
}

 

 

 

주요 기능 정리

  • 기본적인 목록 조회, 페이징
  • 제목/작성자 검색
  • 댓글수, 첨부파일 아이콘 표시
  • 컬럼 정렬 (작성일 기준 내림차순 기본)
  • 데이터 없을 때 메시지 처리
  • 반응형 너비 조정

 

실행하면서 체크할 것들

  • Network 탭에서 요청/응답 확인
  • 검색 시 파라미터 제대로 가는지
  • 페이징 숫자 맞는지
  • 정렬 제대로 되는지
  • 상세페이지 연결 OK인지
  • 스타일 깨지는 거 없는지

이거 기반으로 필요한 기능 추가하면서 쓰면 됨!