💡 "Vue 3 SFC + IBSheet8 대용량 그리드 + Element Plus Dialog 모달 연동 가이드"
📌 AA팀 개발자 교육 문서 - Chapter 3
이 문서에서는 Vue 3 (Composition API + <script setup>) 기반으로 IBSheet8 그리드와 Element Plus el-dialog 모달 팝업을 연동하여 데이터 조회, 등록, 수정, 삭제(CRUD)를 연동하는 표준 가이드를 제공합니다.
*.vue) 생성 & 라우터 추가src/views/sample/notice/index.vuesrc/router/index.js{
path: '/sample/notice',
component: Layout,
hidden: false,
children: [
{
path: 'index',
component: () => import('@/views/sample/notice/index.vue'),
name: 'SampleNotice',
meta: { title: '공지사항 관리', icon: 'message' }
}
]
}
공지사항 관리 등록 (/sample/notice/index)sample:notice:list, sample:notice:add, sample:notice:edit, sample:notice:remove)index.vue)<template>
<div class="app-container">
<!-- 검색 툴바 -->
<el-form :inline="true" :model="queryParams">
<el-form-item label="검색어">
<el-input v-model="queryParams.noticeTitle" placeholder="제목을 입력하세요" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">조회</el-button>
<el-button type="success" icon="Plus" @click="handleAdd">신규 등록</el-button>
</el-form-item>
</el-form>
<!-- IBSheet8 컨테이너 -->
<div id="sheetContainer" style="width: 100%; height: 500px;"></div>
<!-- 등록/수정 Dialog 모달 팝업 -->
<el-dialog :title="dialogTitle" v-model="open" width="600px" append-to-body>
<el-form :model="form" ref="noticeRef" label-width="100px">
<el-form-item label="제목" prop="noticeTitle">
<el-input v-model="form.noticeTitle" placeholder="제목 입력" />
</el-form-item>
<el-form-item label="내용" prop="noticeContent">
<el-input v-model="form.noticeContent" type="textarea" rows="4" placeholder="내용 입력" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="open = false">취소</el-button>
<el-button type="primary" @click="submitForm">저장</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted, reactive } from 'vue'
import { listNotice, addNotice, updateNotice, delNotice } from '@/api/sample/notice'
const open = ref(false)
const dialogTitle = ref('')
const noticeRef = ref(null)
const queryParams = reactive({ noticeTitle: '' })
const form = reactive({ noticeId: null, noticeTitle: '', noticeContent: '' })
let sheetInstance = null
onMounted(() => {
const options = {
Cfg: { SearchMode: 2, CanSort: 1 },
Cols: [
{ Header: "No", Name: "SEQ", Type: "Int", Width: 60, Align: "Center" },
{ Header: "제목", Name: "noticeTitle", Type: "Text", Width: 300 },
{ Header: "등록일", Name: "createTime", Type: "Text", Width: 150, Align: "Center" }
]
}
IBSheet.create({ id: "sheetContainer", el: "sheetContainer", options: options })
.then(sheet => {
sheetInstance = sheet
handleQuery()
})
})
const handleQuery = () => {
listNotice(queryParams).then(res => {
sheetInstance.loadSearchData(res.rows)
})
}
const handleAdd = () => {
form.noticeId = null
form.noticeTitle = ''
form.noticeContent = ''
dialogTitle.value = '공지사항 신규 등록'
open.value = true
}
const submitForm = () => {
if (form.noticeId) {
updateNotice(form).then(() => {
open.value = false
handleQuery()
})
} else {
addNotice(form).then(() => {
open.value = false
handleQuery()
})
}
}
</script>