Vue Mix 예제
설명
“Notice”의 예로 사용자 페이지를 페이지로 제외했습니다.
폴더 구조
vue-mix/
├── componets/
│ ├── NoticeForm.js
│ └── NoticeList.js
├── service/
│ └── notice-admin-svc.js
├── app.js
└── admin.html
admin.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Notice Admin Page</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id="app" class="container mt-3">
<h2>Notice Admin Page</h2>
<h5>Key Features: List inquiry/modification/deletion</h5>
<p>Data is transmitted when modified or deleted from the test page, but it is not actually processed.</p>
<notice-list :bind-model="bindModel"
@select-notice="selectNotice">
</notice-list>
<notice-form v-if="selectedNotice"
:status-options="statusOptions"
:bind-model="bindModel"
@deselect-notice="deselectNotice"
>
</notice-form>
</div>
<script src="https://unpkg.com/vue@3.3.4/dist/vue.global.prod.js"></script>
<script src="/dist/bindmodel.pack.min.js"></script>
<script src="app.js" type="module"></script>
</body>
</html>
app.js
import NoticeList from './components/NoticeList.js';
import NoticeForm from './components/NoticeForm.js';
import NoticeAdminService from './service/notice-admin-svc.js'
const { createApp, ref } = Vue
const bm = new _L.BindModel(new NoticeAdminService());
bm.url =' /notice/data/list.json';
const app = createApp({
data() {
return {
notices: [],
selectedNotice: null,
statusOptions: {
'D': 'Standby',
'A': 'Activation',
'H': 'Hidden'
},
bindModel: bm,
};
},
methods: {
selectNotice(idx) {
this.selectedNotice = idx;
},
deselectNotice() {
this.selectedNotice = null;
},
},
components: {
'notice-list': NoticeList,
'notice-form': NoticeForm
}
});
app.mount('#app');
service/notice-admin-svc.js
class NoticeAdminService {
constructor() {
var _this = this;
var _template = null; // Handlebars template
this.items = {
ntc_idx: { required: true },
title: { required: true }
},
this.command = {
create: {
},
read: {
outputOption: 3,
},
update: {
cbBind(bind, cmd, setup) {
console.warn('Caution: Send to the test server, but the data is not reflected.', setup.data);
},
},
delete: {
cbValid(valid, cmd) {
if (confirm('Are you sure you want to delete it?')) return true;
},
cbBind(bind, cmd, setup) {
console.warn('Caution: Send to the test server, but the data is not reflected.', setup.data);
},
},
list: {
outputOption: 1,
}
};
this.mapping = {
ntc_idx: { read: ['bind', 'output'], update: 'bind', delete: ['valid', 'bind'] },
title: { read: 'output', update: ['valid', 'bind'], },
contents: { read: 'output', update: 'bind' },
top_yn: { read: 'output', update: ['valid', 'bind'], },
active_cd: { read: 'output', update: ['valid', 'bind'], },
create_dt: { read: 'output' },
};
}
}
export {
NoticeAdminService as default,
NoticeAdminService
}
components/NoticeForm.js
export default {
props: ['statusOptions', 'bindModel'],
data() {
return {
formData: { ...this.notice }
};
},
emits: ['deselect-notice'],
template: `
<div id="class-form">
<form @submit.prevent="updateClick">
<div class="form-group">
<label>날짜</label>
<p id="create_dt"></p>
</div>
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" v-model="bindModel.cols.title.value" required>
</div>
<div class="form-group">
<label for="contents">Content</label>
<textarea class="form-control" id="contents" v-model="bindModel.cols.contents.value" rows="3"></textarea>
</div>
<div class="row">
<div class="col">
<div class="form-check">
<input type="checkbox" class="form-check-input" id="check1" v-model="bindModel.cols.top_yn.value" true-value="Y" false-value="N">
<label class="form-check-label" for="check1">Top notice</label>
</div>
</div>
<div class="col">
<div class="form-check" v-for="(label, value) in statusOptions" :key="value">
<input type="radio" class="form-check-input" :id="\`radio\${value}\`" v-model="bindModel.cols.active_cd.value" :value="value">
<label class="form-check-label" :for="\`radio\${value}\`"></label>
</div>
</div>
</div>
<button type="submit" class="btn btn-primary mt-3">Update</button>
<button type="button" class="btn btn-danger mt-3" @click="deleteClick">Delete</button>
<button type="button" class="btn btn-secondary mt-3" @click="$emit('deselect-notice')">List</button>
</form>
</div>
`,
async created() {
var _this = this;
this.bindModel.cmd['update'].cbEnd = function(status, cmd, res) {
if (res) {
alert('The post has been modified.');
_this.$emit('deselect-notice');
}
};
this.bindModel.cmd['delete'].cbEnd = function(status, cmd, res) {
if (res) {
alert('The post has been deleted.');
_this.$emit('deselect-notice');
}
};
},
methods: {
updateClick() {
for (var prop in this.formData) {
this.bindModel.columns[prop].value = this.formData[prop];
}
this.bindModel.cmd['update'].execute();
},
deleteClick() {
this.bindModel.cmd['delete'].execute();
}
}
};
components/NoticeList.js
export default {
props: ['bindModel'],
emits: ['select-notice'],
template: `
<table class="table">
<thead>
<tr>
<th>Title</th>
<th>Status</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<tr v-if="bindModel.cmd.list.output.rows.length === 0">
<td colspan="3">There is no content.</td>
</tr>
<tr v-for="(notice, index) in bindModel.cmd.list.output.rows" :key="notice.ntc_idx">
<td><a href="#" @click.prevent="readClick(index)"></a></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
`,
async created() {
await this.bindModel.cmd['list'].execute();
},
methods: {
async readClick(idx) {
this.bindModel.cmd['read'].outputOption.index = Number(idx);
await this.bindModel.cmd['read'].execute();
this.$emit('select-notice', idx);
}
}
};