こちらの記事の続編です。 VueとSpringで作成したプロジェクトの構築手順の備忘録。
備忘録のため、詳細な説明を省略している部分があります。
今回はフロントエンドから作っていこうと思います。 まず、DankaList.vueに必要な処理やと要素など色々詰め込みます。 一旦ユーザー情報を固定値で入れて動作確認優先で実装を進めようと思います(エラーの要因を挟みたくない) これで実際に画面を動かしてみると、奇跡的に全て正常に動きました・・・笑 今回はここまでです!
コードの羅列みたいになってしまっていますが、、、ご容赦を、、、
内容を逐一解説する元気がなかったため、気になる点がありましたらコメントなどいただけますと幸いです。 お付き合い頂きありがとうございました!まえがき
目的
前提
環境
やること
完成画面
画面遷移
新規作成仕様
編集仕様
削除仕様
実装~フロントエンド~
<template>
<div>
<template>
<v-data-table
:headers="headers"
:items="dankaList"
:page.sync="page"
:items-per-page="itemsPerPage"
sort-by="calories"
class="elevation-1"
@page-count="pageCount = $event"
hide-default-footer
>
<template v-slot:top>
<v-toolbar flat>
<v-toolbar-title>檀家一覧</v-toolbar-title>
<v-spacer></v-spacer>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on, attrs }">
<v-btn
color="primary"
dark
class="mb-2"
v-bind="attrs"
v-on="on"
>
新規作成
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkSeshuName"
label="施主名"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkKoshuName"
label="戸主名"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkKoshuName2"
label="戸主名2"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkPhonenumber1"
label="電話番号"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkEmail1"
label="メールアドレス"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkAddress1"
label="住所"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
v-model="editedItem.dnkBikou1"
label="備考"
></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="close">
取消
</v-btn>
<v-btn color="blue darken-1" text @click="save()">
保存
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogDelete" max-width="500px">
<v-card>
<v-card-title class="text-h5"
>削除してもよろしいですか?</v-card-title
>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="closeDelete"
>取消</v-btn
>
<v-btn color="red darken-1" text @click="deleteItemConfirm"
>削除</v-btn
>
<v-spacer></v-spacer>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
</template>
<template v-slot:[`item.actions`]="{ item }">
<v-icon color="green" class="mr-6" @click="editItem(item)">
mdi-pencil
</v-icon>
<v-icon color="red" @click="deleteItem(item)"> mdi-delete </v-icon>
</template>
<template v-slot:no-data>
<v-btn color="primary" @click="getDanakList()"> Reset </v-btn>
</template>
</v-data-table>
<div class="text-right pt-2">
<v-pagination v-model="page" :length="pageCount"></v-pagination>
<v-text-field
:value="itemsPerPage"
label="Items per page"
type="number"
min="-1"
max="15"
@input="itemsPerPage = parseInt($event, 10)"
></v-text-field>
</div>
</template>
</div>
</template>
<script>
export default {
name: "DankaList",
data: () => ({
dankaList: [],
page: 1,
pageCount: 0,
itemsPerPage: 10,
dialog: false,
dialogDelete: false,
headers: [
{
text: "施主名",
align: "start",
value: "dnkSeshuName",
},
{ text: "戸主名", value: "dnkKoshuName" },
{ text: "戸主名2", value: "dnkKoshuName2" },
{ text: "住所", value: "dnkAddress1" },
{ text: "電話番号", value: "dnkPhonenumber1" },
{ text: "メールアドレス", value: "dnkEmail1" },
{ text: "備考", value: "dnkBikou1" },
{ text: "Actions", value: "actions", sortable: false },
],
editedIndex: -1,
editedItem: {
dnkSeshuName: "",
dnkKoshuName: "",
dnkKoshuName2: "",
dnkAddress1: "",
dnkPhonenumber1: "",
dnkEmail1: "",
dnkBikou1: ""
},
defaultItem: {
dnkSeshuName: "",
dnkKoshuName: "",
dnkKoshuName2: "",
dnkAddress1: "",
dnkPhonenumber1: "",
dnkEmail1: "",
dnkBikou1: ""
},
}),
computed: {
formTitle() {
return this.editedIndex === -1 ? "新規登録" : "編集";
},
},
watch: {
dialog(val) {
val || this.close();
},
dialogDelete(val) {
val || this.closeDelete();
},
},
created() {
this.getDanakList();
},
methods: {
getDanakList() {
const _this = this;
this.$axios.get("/danka").then(response => {
console.log(response.data);
_this.dankaList = response.data;
});
},
editItem(item) {
this.editedIndex = this.dankaList.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialog = true;
},
deleteItem(item) {
this.editedIndex = this.dankaList.indexOf(item);
this.editedItem = Object.assign({}, item);
this.dialogDelete = true;
},
deleteItemConfirm() {
this.dankaList.splice(this.editedIndex, 1);
this.delete();
this.closeDelete();
},
close() {
this.dialog = false;
this.$nextTick(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
});
},
closeDelete() {
this.dialogDelete = false;
this.$nextTick(() => {
this.editedItem = Object.assign({}, this.defaultItem);
this.editedIndex = -1;
});
},
delete(){
const dankaId = this.editedIndex + 1;
this.$axios.post(`/danka/delete/${dankaId}`).then(() => {
console.log("削除に成功しました");
})
},
save() {
// 編集の場合はif句の処理、新規登録の場合はelse句の処理
if (this.editedIndex > -1) {
const dankaId = this.editedIndex + 1;
Object.assign(this.dankaList[this.editedIndex], this.editedItem);
this.$axios.post(`/danka/update/${dankaId}`, {
seshuName: this.editedItem.seshuName,
koshuName: this.editedItem.koshuName,
koshuName2: this.editedItem.koshuName2,
address: this.editedItem.address,
phonenumber: this.editedItem.phonenumber,
mailAddress: this.editedItem.mailAddress,
remark: this.editedItem.remark
}).then(() => {
console.log("更新に成功しました");
})
} else {
// const _this = this;
this.$axios.post(`/danka/save`, {
seshuName: this.editedItem.seshuName,
koshuName: this.editedItem.koshuName,
koshuName2: this.editedItem.koshuName2,
address: this.editedItem.address,
phonenumber: this.editedItem.phonenumber,
mailAddress: this.editedItem.mailAddress,
remark: this.editedItem.remark
}).then(() => {
console.log("保存に成功しました");
})
}
this.close();
},
},
};
</script>
実装~バックエンド~
private Integer dnkId = 0;
private String seshuName = "";
private String koshuName = "";
private String koshuName2 = "";
private String address = "";
private String phonenumber = "";
private String mailAddress = "";
private String remark = "";
// setter/getter省略
@PostMapping("/danka/save")
@ResponseBody
public void saveDanka(@RequestBody DankaForm dankaSaveForm) {
TblDankaEntity tblDanka;
tblDanka = setDanakFormToTblDanka(dankaSaveForm);
dankaService.saveTblDanka(tblDanka);
}
@PostMapping("/danka/update/{dankaId}")
@ResponseBody
public void updateDanka(@PathVariable("dankaId") String dankaId,
@RequestBody DankaForm dankaSaveForm) {
TblDankaEntity tblDanka;
tblDanka = setDanakFormToTblDanka(dankaSaveForm);
//formの値をsetしてからIDをsetすること
tblDanka.setDnkId(Integer.parseInt(dankaId));
dankaService.updateTblDanka(tblDanka);
}
@PostMapping("/danka/delete/{dankaId}")
@ResponseBody
public void deleteUpdateDanka(@PathVariable("dankaId") String dankaId) {
dankaService.deleteUpdateTblDanka(Integer.parseInt(dankaId));
}
/*
* 檀家Formの入力値を檀家Entityにセットするメソッド
* @param dankaSaveForm
* @return tblDanka
*/
private TblDankaEntity setDanakFormToTblDanka(DankaForm dankaForm) {
TblDankaEntity tblDanka = new TblDankaEntity();
String now = getNowDateTime();
tblDanka.setDnkId(dankaForm.getDnkId());
tblDanka.setCreatedAt(now);
// TODO 登録者のユーザーIDを登録できるように変更すること
tblDanka.setCreatedBy("rinsyou@gmail.com");
tblDanka.setDnkSeshuName(dankaForm.getSeshuName());
tblDanka.setDnkKoshuName(dankaForm.getKoshuName());
tblDanka.setDnkKoshuName2(dankaForm.getKoshuName2());
tblDanka.setDnkPhonenumber1(dankaForm.getPhonenumber());
tblDanka.setDnkEmail1(dankaForm.getMailAddress());
tblDanka.setDnkAddress1(dankaForm.getAddress());
tblDanka.setDnkBikou1(dankaForm.getRemark());
tblDanka.setIsDeleted("0");
return tblDanka;
}
/**
* 現在日時をyyyy/MM/dd HH:mm:ss形式で取得する.<br>
*/
public static String getNowDateTime(){
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
final Date date = new Date(System.currentTimeMillis());
return df.format(date);
}
public void saveTblDanka(TblDankaEntity tblDanka) {
dankaMapper.save(tblDanka);
}
@Transactional
/*
* delete/insert
*/
public void updateTblDanka(TblDankaEntity tblDanka) {
Integer dankaId = tblDanka.getDnkId();
//TODO 自作例外を作成して画面にはエラーメッセージを表示させる
if(!isExistTargetById(dankaId)) {return;}
dankaMapper.deleteByDankaId(dankaId);
dankaMapper.insertDanka(tblDanka);
}
/**
* Logical delete
* @param dankaId
*/
public void deleteUpdateTblDanka(Integer dankaId) {
dankaMapper.deleteUpdateById(dankaId);
}
/**
* 対象のデータが存在するかチェックするメソッド
* @param dankaId
* @return true/false
*/
//TODO 汎用的なメソッドとして切り出す
private boolean isExistTargetById(Integer dankaId) {
boolean result = false;
Optional<TblDankaEntity> target = dankaMapper.findOneDankaById(dankaId);
if(target.isPresent()) {
result = true;
} else {
return result;
}
return result;
}
void deleteByDankaId(Integer dankaId);
Optional<TblDankaEntity> findOneDankaById(Integer dankaId);
void saveDanka(TblDankaEntity tblDanka);
void deleteUpdateById(Integer dankaId);
<mapper namespace="jp.co.tms.domain.mapper.DankaMapper">
<select id="findAllDanka" resultType="jp.co.tms.domain.entity.TblDankaEntity">
SELECT *
FROM tbl_danka
WHERE is_deleted = 0;
</select>
<select id="findOneDankaById" resultType="jp.co.temple.domain.entity.TblDanka">
SELECT *
FROM tbl_danka
WHERE dnk_id = #{dankaId}
</select>
<delete id="deleteByDankaId" timeout="20">
DELETE
FROM tbl_danka
WHERE dnk_id = #{dankaId}
</delete>
<insert id="saveDanka">
INSERT INTO tbl_danka
(`dnk_id`,
`dnk_seshu_name`,
`dnk_koshu_name`,
`dnk_koshu_name2`,
`dnk_address1`,
`dnk_bikou1`,
`dnk_phonenumber1`,
`dnk_email1`,
`created_at`,
`created_by`,
`updated_by`,
`is_deleted`,
`updated_at`)
VALUES
(#{dnkId},
#{dnkSeshuName},
#{dnkKoshuName},
#{dnkKoshuName2},
#{dnkAddress1},
#{dnkBikou1},
#{dnkPhonenumber1},
#{dnkEmail1},
#{createdAt},
#{createdBy},
#{updatedBy},
#{isDeleted},
#{updatedAt})
</insert>
<update id="deleteUpdateById">
UPDATE
tbl_danka
SET
is_deleted = 1
WHERE
dnk_id = #{dankaId}
</update>