昨天我們完成了題組的新增及重新整理了題目的CRUD,不過題組應該也要可以修改及刪除,但目前的版面配置空間有限,所以我們使用 icon 來協助完成這兩個功能。
不過這邊有個問題要小心,題目中有題庫和題組的關聯,那麼當題組或題庫被刪除時,題目該怎麼處理?所以如果只是編輯的話沒有什麼問題,但是當要刪除時,應該要先確認一下有沒有關聯的題目存在,並做出對應的提示,目前我會先檔下來,只要題庫或題組有關聯的題目在,就只能編輯不能刪除。
參考官網的[Set Up with Vue]
npm i --save @fortawesome/fontawesome-svg-core
安裝免費版的 icon 套件
npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
npm i --save @fortawesome/free-brands-svg-icons
安裝 vue3 用的 icon component
# for Vue 3.x
npm i --save @fortawesome/vue-fontawesome@latest-3
接著到 [Add Icons with Vue] 來看看如何把icon加入到 vue 中;
resources\js\Pages\Backstage\Subjects.vue
...略
/* 載入fontawesome的專用library */
import { library } from '@fortawesome/fontawesome-svg-core'
/* 引入fontawesome的專用組件 */
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
/* 引入要使用的icon名稱 */
import { faFilePen,faTrashCan } from '@fortawesome/free-solid-svg-icons'
/* 將要使用的icon加入到library中 */
library.add(faFilePen,faTrashCan)
...略
<div v-else>
<button class="px-4 py-2 border rounded-lg hover:bg-sky-400
hove:text-sky-900 text-sky-700 bg-sky-200"
v-for="group in groups"
:key="group.id">
{{ group.name }}
</button>
<!-- 使用組件來引入icon -->
<font-awesome-icon icon="fa-solid fa-file-pen" />
<font-awesome-icon icon="fa-solid fa-trash-can" />
</div>
調整一下icon的位置在題組按鈕的右上和右下,一個設成綠色的,一個設成紅色的,同時我們在題組按鈕上設定滑鼠滑入滑出時icon的顯示隱蔵效果:
resources\js\Pages\Backstage\Subjects.vue
<script setup>
import { ref } from 'vue';
//依據題組的數量來宣告一個陣列,並預設填上false
const hover=ref((new Array(props.groups.length)).fill(false))
</script>
<template>
<div v-else>
<!--在按鈕上建立滑鼠移入移出的事件,並切換hover的true及false值-->
<button class="px-4 py-2 border rounded-lg hover:bg-sky-400
hove:text-sky-900 text-sky-700 bg-sky-200 relative"
v-for="group,idx in groups"
:key="group.id"
@mouseover="hover[idx]=!hover[idx]"
@mouseout="hover[idx]=!hover[idx]">
{{ group.name }}
<!-- 使用組件來引入icon -->
<font-awesome-icon icon="fa-solid fa-file-pen"
class="absolute -top-1 -right-3 text-green-600"
:class="{'block':hover[idx],'hidden':!hover[idx]}" />
<font-awesome-icon icon="fa-solid fa-trash-can"
class="absolute -bottom-1 -right-2 text-red-600"
:class="{'block':hover[idx],'hidden':!hover[idx]}" />
</button>
</div>
</template>
接著在編輯及刪除的icon上加上刪除的路由:
resources\js\Pages\Backstage\Subjects.vue
.....略
<Link :href="route('bankgroup.edit',group.id)">
<font-awesome-icon icon="fa-solid fa-file-pen"
class="absolute -top-1 -right-3 text-green-600"
:class="{'block':hover,'hidden':!hover}" />
</Link>
<Link :href="route('bankgroup.destroy',group.id)">
<font-awesome-icon icon="fa-solid fa-trash-can"
class="absolute -bottom-1 -right-2 text-red-600"
:class="{'block':hover,'hidden':!hover}" />
</Link>
調整一下 BankGroupConroller
中的內容,把需要帶的資料和提示功能也加上去:
app\Http\Controllers\BankGroupController.php
function edit($id)
{
$group=$this->bankgroup->find($id);
$bank=$group->bank;
unset($group->bank); //移除不需要傳到前端的資料,
return Inertia::render('Backstage/BankGroupForm',[
'header'=>'編輯題組',
'button'=>'修改',
'group'=>$group,
'bank'=>$bank
]);
}
function update(Request $request,$id)
{
$this->bankgroup->update($request->input(),$id);
//善用邏輯拆分及資料關聯,可以很方便的取得需要的資料,
//比如在這邊可以從題組的id去找出題庫再取得題庫的code回傳給路由
return redirect()->route('bank.subjects',$this->bankgroup->find($id)->bank->code);
}
function destroy($id)
{
//透過關聯判斷題組是否有關聯的題目存在
if($this->bankgroup->find($id)->subjects()->exists()){
//如果有關聯題目存在,則回傳錯誤息
return redirect()->back()->withErrors(['bankgroup'=>'關聯題目存在,無法刪除題組']);
}
//刪除題組
$this->bankgroup->destroy($id);
//導回頁面
return redirect()->back();
}
因為題組的刪除可能會有錯誤訊息回傳,所以我們要在題目列表畫面偵錯誤訊息,這個機制 Inertia
已經幫我們做掉了,laravel回傳的錯誤訊息都會集中在全域的 errors
中,我們只要在組件中把這個屬性接進來就可以了:
resources\js\Pages\Backstage\Subjects.vue
<script setup>
....略
const props = defineProps({ subjects: Array,
groups:Array,
count: Number ,
bank:String,
errors:Object}); //增加一個errors的屬性
</script>
<template>
<!--這個錯誤訊息區塊會依據bankgroup是否有資料來顯示或隱藏-->
<div v-if="errors.bankgroup"
class="text-red-100 px-3 py-1.5 rounded-lg bg-red-500 my-2">
{{ errors.bankgroup }}
</div>
</template>
這樣,整套題庫到題目的後台功能總算是比較完整了,細節的部份可以再自行調整,後面如果有空我會再補上,因為我開始覺得30天講不完這整個系統的設計,我太輕敵了,哈哈哈哈哈.......