오늘의 Vue.js 실습 목표는 "공지사항/게시판 만들어보기!" 입니다.
본 게시글에서 다루는 사항은 공지사항/게시판 기본(테이블) 화면의 기능을 구현하는 과정입니다.
Spring Boot로 구현한 REST API를 통해 DB 데이터를 조작하는 과정은 별도의 포스팅에서 다룰 예정입니다.
공지사항/게시판 구현하기 - 기본(리스트/테이블) 화면
사전 준비
아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.
결과 이미지
구현하기에 앞서 본 글을 따라하시면 아래와 같이 공지사항 기본(리스트, 테이블) 화면의 레이아웃이 구성되는 것을 확인하실 수 있습니다.
▶ 초기 화면
▶ 테이블에서 한 행을 선택한 경우
▶ 삭제 버튼을 클릭한 경우
소스 코드
src\components\user-web\notice\NoticeList.vue
전체 코드를 확인하실 분들은 아래 더보기를 클릭해주세요.
더보기
<template>
<div class="ma-md-5">
<div class="d-flex justify-end mt-5">
<!-- For Notice List Manipulation > Register -->
<v-btn
text
outlined
class="mx-md-1 elevation-2"
:disabled="!hasSelectedRow()"
@click="viewNotice"
>VIEW DETAIL
</v-btn>
<!-- For Notice List Manipulation > Register -->
<v-btn text outlined class="mx-md-1 elevation-2" @click="registerNotice"
>REGISTER
</v-btn>
<!-- For Notice List Manipulation > Modify -->
<v-btn
text
outlined
class="mx-md-1 elevation-2"
:disabled="!hasSelectedRow()"
@click="modifyNotice"
>MODIFY
</v-btn>
<!-- For Notice List Manipulation > Delete -->
<v-dialog v-model="dialogDelete" persistent max-width="290">
<template v-slot:activator="{ on, attrs }">
<v-btn
text
outlined
class="mx-md-1 elevation-2"
:disabled="!hasSelectedRow()"
v-bind="attrs"
v-on="on"
>DELETE
</v-btn>
</template>
<v-card>
<v-card-title class="text-h5">
Are you sure you want to delete this notice?
</v-card-title>
<v-card-text
>Deleted notices cannot be restored, and are immediately reflected
on the user portal after deletion.</v-card-text
>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialogDelete = false">
Cancel
</v-btn>
<v-btn color="blue darken-1" text @click="deleteNotice">
Confirm
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
<!-- For Notice List -->
<v-data-table
single-select
show-select
class="mt-md-2 elevation-5"
v-model="selectedRow"
:headers="headers"
:items="data"
:items-per-page="10"
>
</v-data-table>
</div>
</template>
<script>
const MODE_VIEW = "VIEW";
const MODE_REGISTER = "REGISTER";
const MODE_MODIFY = "MODIFY";
const MODE_DELETE = "DELETE";
export default {
data() {
return {
selectedRow: [],
dialogDelete: false,
// For Notice List
headers: [
{
text: "Category",
value: "category",
},
{
text: "Title",
value: "title",
},
{
text: "Date",
value: "date",
},
{
text: "Name",
value: "name",
},
],
data: [
{
id: "1",
category: "Competition",
title: "The 3rd Competition Open!",
date: "2022/11/01",
name: "SYSTEM",
},
{
id: "2",
category: "System Check",
title: "2022/12/10 System Check",
date: "2022/12/01",
name: "SYSTEM",
},
{
id: "3",
category: "System Check",
title: "2022/12/15 System Check",
date: "2022/12/10",
name: "SYSTEM",
},
{
id: "4",
category: "System Check",
title: "2023/01/01 System Check",
date: "2022/12/21",
name: "SYSTEM",
},
{
id: "5",
category: "Competiton",
title: "The 4th Competition Open!",
date: "2023/01/01",
name: "SYSTEM",
},
{
id: "6",
category: "Etc",
title: "Test Announcement",
date: "2023/01/05",
name: "SYSTEM",
},
],
};
},
methods: {
hasSelectedRow: function () {
return this.selectedRow.length > 0;
},
changeMode: function (mode, notice) {
this.$emit("changeMode", mode, notice);
},
viewNotice: function () {
this.changeMode(MODE_VIEW, this.selectedRow);
},
registerNotice: function () {
if (this.hasSelectedRow()) {
this.selectedRow = [];
}
this.changeMode(MODE_REGISTER, this.selectedRow);
},
modifyNotice: function () {
this.changeMode(MODE_MODIFY, this.selectedRow);
},
deleteNotice: function () {
this.dialogDelete = false;
this.changeMode(MODE_DELETE, this.selectedRow);
},
},
};
</script>
<style>
tr.v-data-table__selected {
background: lightgoldenrodyellow !important;
}
</style>
<template>
<template>
<div class="ma-md-5">
<div class="d-flex justify-end mt-5">
<!-- For Notice List Manipulation > Detail View -->
<v-btn
...
:disabled="!hasSelectedRow()"
@click="viewNotice"
>VIEW DETAIL
</v-btn>
<!-- For Notice List Manipulation > Register -->
<v-btn
...
@click="registerNotice"
>REGISTER
</v-btn>
<!-- For Notice List Manipulation > Modify -->
<v-btn
...
:disabled="!hasSelectedRow()"
@click="modifyNotice"
>MODIFY
</v-btn>
<!-- For Notice List Manipulation > Delete -->
<v-dialog v-model="dialogDelete" persistent max-width="290">
<template v-slot:activator="{ on, attrs }">
<v-btn
...
:disabled="!hasSelectedRow()"
v-bind="attrs"
v-on="on"
>DELETE
</v-btn>
</template>
<v-card>
<v-card-title class="text-h5">
Are you sure you want to delete this notice?
</v-card-title>
<v-card-text
>Deleted notices cannot be restored, and are immediately reflected
on the user portal after deletion.</v-card-text
>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialogDelete = false">
Cancel
</v-btn>
<v-btn color="blue darken-1" text @click="deleteNotice">
Confirm
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</div>
<!-- For Notice List -->
<v-data-table
...
v-model="selectedRow"
...
>
</v-data-table>
</div>
</template>
- UI
- :disabled = 버튼 요소의 Enable 상태를 테이블의 행 선택 여부를 감지하여 변화되도록 함수 호출 코드 정의
- 삭제 버튼 = 버튼 클릭시 팝업창이 띄워지도록 관련 코드 추가
- Event
- @click = 버튼 요소에 이벤트 발생시 호출할 함수를 연결하는 코드 정의
- v-model = 버튼 외 요소에 변경된 값을 감지하는 코드 정의
<script>
<script>
const MODE_VIEW = "VIEW";
const MODE_REGISTER = "REGISTER";
const MODE_MODIFY = "MODIFY";
const MODE_DELETE = "DELETE";
export default {
data() {
return {
selectedRow: [],
dialogDelete: false,
// For Notice List
headers: [
...
],
data: [
...
]
};
},
methods: {
hasSelectedRow: function () {
return this.selectedRow.length > 0;
},
changeMode: function (mode, notice) {
this.$emit("changeMode", mode, notice);
},
viewNotice: function () {
this.changeMode(MODE_VIEW, this.selectedRow);
},
registerNotice: function () {
if (this.hasSelectedRow()) {
this.selectedRow = [];
}
this.changeMode(MODE_REGISTER, this.selectedRow);
},
modifyNotice: function () {
this.changeMode(MODE_MODIFY, this.selectedRow);
},
deleteNotice: function () {
this.dialogDelete = false;
this.changeMode(MODE_DELETE, this.selectedRow);
},
},
};
</script>
- data 영역
- selectedRow: 테이블에서 선택된 행 정보가 담긴 변수
- dialogDelete: 삭제 버튼 클릭시 팝업되는 다이얼로그의 활성 여부 정보가 담긴 변수
- methods 영역
- hasSelectedRow(): 테이블에서 선택된 행이 있는지 확인하는 함수
- changeMode(): 모드 변경에 따른 상위 컴포넌트에 정보를 전달하는 함수
- 전달 정보: 조작 모드(등록, 삭제, 수정, 상세보기), 선택된 공지사항/게시글 정보
- viewNotice(): '상세보기' 관련 처리 함수
- registerNotice(): '등록' 관련 처리 함수
- 테이블에 선택된 행이 있으면 선택 취소 처리
- modifyNotice(): '수정' 관련 처리 함수
- deleteNotice(): '삭제' 관련 처리 함수
- 팝업된 다이얼로그를 표시 해지하도록 dialogDelete의 변수값 false 설정
- 참고 사항
- script에 선언된 const 변수(MODE_%)를 NoticeList.vue, NoticeDetail.vue, BaseNotice.vue에서 각각 관리하는 것이 아닌 하나의 파일에서 관리하고 사용할 수 있도록 변경하는 작업이 필요합니다.
<style>
<style>
tr.v-data-table__selected {
background: lightgoldenrodyellow !important;
}
</style>
- 테이블에서 한 행이 클릭되었을 때 표시될 background 정보 설정
References
- Vuetify Tutorial: https://vuetifyjs.com/en/
- Vue.js 공식 사이트: https://vuejs.org/guide/quick-start.html
'Programming > Vue' 카테고리의 다른 글
[실습] 뷰(Vue)로 공지사항/게시판 구현하기 - Root/상위 컴포넌트 화면 기능 개발 (0) | 2023.02.06 |
---|---|
[실습] 뷰(Vue)로 공지사항/게시판 구현하기 - 상세 화면 기능 개발 (0) | 2023.02.03 |
Vue와 스프링부트(Spring Boot) 연동/연결하기 (0) | 2023.02.01 |
"'v-slot' directive doesn't support any modifier" 오류 해결 방법 (0) | 2023.01.09 |
[실습] 뷰(Vue.js)로 관리자/직원 전용 Web Application 개발하기 - 메뉴에 공지사항/게시판 연동하기 (0) | 2023.01.06 |
댓글