D21 - 實作分類管理:建立分類列表與新增/編輯頁面

更新於 2024/12/15閱讀時間約 19 分鐘

哈囉,大家好!在前一篇文章中,我們成功地實作了銀行帳戶管理的功能,建立了銀行帳戶列表頁面以及新增/編輯頁面。


今天,我們將繼續完善我們的個人財務管理系統,專注於分類管理的開發。分類管理是財務管理系統中的重要組成部分,透過分類,我們可以更好地組織和分析收入與支出。接下來,我們將建立分類列表頁面以及新增/編輯分類頁面,讓使用者可以方便地管理他們的收入和支出分類。


一、建立分類列表頁面

首先,我們要建立分類列表頁面,讓使用者可以查看、編輯和刪除他們的分類。

1. 建立頁面檔案

在 pages/ 目錄下建立 categories.vue 檔案。

touch pages/categories.vue

2. 編寫頁面結構

在 categories.vue 中,我們建立基本的頁面結構,顯示分類列表。

<template>
<div>
<h2 class="text-2xl font-bold mb-4">分類管理</h2>
<div v-if="error" class="text-red-500">
{{ error }}
</div>
<div v-else>
<button @click="goToAddCategory" class="bg-blue-600 text-white px-4 py-2 mb-4">
新增分類
</button>
<table class="w-full text-left">
<thead>
<tr>
<th class="border px-4 py-2">分類名稱</th>
<th class="border px-4 py-2">類型</th>
<th class="border px-4 py-2">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="category in categories" :key="category.id">
<td class="border px-4 py-2">{{ category.name }}</td>
<td class="border px-4 py-2">{{ category.type === 'income' ? '收入' : '支出' }}</td>
<td class="border px-4 py-2">
<button @click="goToEditCategory(category.id)" class="text-blue-600 mr-2">
編輯
</button>
<button @click="deleteCategory(category.id)" class="text-red-600">
刪除
</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>

<script>
export default {
middleware: 'auth',
data() {
return {
categories: [],
error: null,
}
},
async mounted() {
try {
const response = await this.$axios.get('/api/categories')
if (response.data.status === 'success') {
this.categories = response.data.data
} else {
this.error = response.data.message || '無法獲取分類資料。'
}
} catch (error) {
this.error = '伺服器發生錯誤,請稍後再試。'
console.error('Error fetching categories:', error)
}
},
methods: {
goToAddCategory() {
this.$router.push('/categories/add')
},
goToEditCategory(id) {
this.$router.push(`/categories/edit/${id}`)
},
async deleteCategory(id) {
if (confirm('確定要刪除這個分類嗎?')) {
try {
await this.$axios.delete(`/api/categories/${id}`)
this.categories = this.categories.filter(category => category.id !== id)
} catch (error) {
alert('刪除失敗,請稍後再試。')
console.error('Error deleting category:', error)
}
}
},
},
}
</script>

<style scoped>
/* 頁面專屬的樣式 */
</style>

3. 說明

  • 資料取得:在 mounted 生命週期鉤子中,我們向後端 API 請求分類列表,並將資料存入 categories。
  • 新增分類:點擊「新增分類」按鈕,導向新增分類的頁面。
  • 編輯分類:在列表中,點擊「編輯」按鈕,導向編輯該分類的頁面。
  • 刪除分類:點擊「刪除」按鈕,彈出確認對話框,確認後發送刪除請求,並從列表中移除該分類。

4. 處理權限保護

  • 使用 middleware: 'auth',確保只有已登入的使用者才能訪問此頁面。

二、建立新增/編輯分類頁面

接下來,我們建立新增和編輯分類的頁面,使用共用的表單元件來實現。

1. 建立頁面檔案

在 pages/categories/ 目錄下建立以下檔案:

mkdir -p pages/categories
touch pages/categories/add.vue
touch pages/categories/_id.vue
touch pages/categories/_form.vue

2. 編寫 _form.vue 元件

在 _form.vue 中,我們建立分類的表單元件,供新增和編輯頁面使用。

<template>
<div>
<h2 class="text-2xl font-bold mb-4">{{ isEdit ? '編輯分類' : '新增分類' }}</h2>
<form @submit.prevent="submitForm">
<div class="mb-4">
<label class="block">分類名稱</label>
<input v-model="form.name" type="text" class="border p-2 w-full" required />
<p v-if="errors.name" class="text-red-500">{{ errors.name }}</p>
</div>
<div class="mb-4">
<label class="block">類型</label>
<select v-model="form.type" class="border p-2 w-full" required>
<option value="">請選擇</option>
<option value="income">收入</option>
<option value="expense">支出</option>
</select>
<p v-if="errors.type" class="text-red-500">{{ errors.type }}</p>
</div>
<div v-if="error" class="text-red-500 mb-4">
{{ error }}
</div>
<button type="submit" class="bg-blue-600 text-white px-4 py-2">
{{ isEdit ? '更新' : '新增' }}
</button>
</form>
</div>
</template>

<script>
export default {
props: {
isEdit: {
type: Boolean,
default: false,
},
categoryId: {
type: Number,
default: null,
},
},
data() {
return {
form: {
name: '',
type: '',
},
errors: {},
error: null,
}
},
async mounted() {
if (this.isEdit && this.categoryId) {
try {
const response = await this.$axios.get(`/api/categories/${this.categoryId}`)
if (response.data.status === 'success') {
this.form = response.data.data
} else {
this.error = response.data.message || '無法獲取分類資料。'
}
} catch (error) {
this.error = '伺服器發生錯誤,請稍後再試。'
console.error('Error fetching category:', error)
}
}
},
methods: {
async submitForm() {
this.errors = {}
this.error = null
try {
if (this.isEdit) {
await this.$axios.put(`/api/categories/${this.categoryId}`, this.form)
} else {
await this.$axios.post('/api/categories', this.form)
}
this.$router.push('/categories')
} catch (error) {
if (error.response && error.response.status === 422) {
this.errors = error.response.data.errors
} else {
this.error = '提交失敗,請稍後再試。'
}
console.error('Error submitting category form:', error)
}
},
},
}
</script>

<style scoped>
/* 元件專屬的樣式 */
</style>

3. 編寫新增與編輯頁面

新增頁面 add.vue

<template>
<FormComponent />
</template>

<script>
import FormComponent from './_form.vue'

export default {
middleware: 'auth',
components: {
FormComponent,
},
}
</script>

<style scoped>
/* 頁面專屬的樣式 */
</style>

編輯頁面 _id.vue

<template>
<FormComponent :isEdit="true" :categoryId="categoryId" />
</template>

<script>
import FormComponent from './_form.vue'

export default {
middleware: 'auth',
components: {
FormComponent,
},
computed: {
categoryId() {
return parseInt(this.$route.params.id)
},
},
}
</script>

<style scoped>
/* 頁面專屬的樣式 */
</style>

4. 說明

  • 共用表單元件:將新增和編輯的表單抽取為 _form.vue,以便重用。
  • 動態路由:使用 _id.vue 處理帶有 id 參數的路由,方便取得要編輯的分類資料。
  • 資料驗證與錯誤處理:在提交表單時,處理後端回傳的驗證錯誤,並顯示在對應的欄位下方。

三、更新導航列

為了方便使用者訪問分類管理頁面,我們需要在導航列中添加對應的連結。

1. 更新 components/Header.vue

如果之前已經有分類管理的連結,可以忽略此步驟,否則請添加以下內容:

<!-- 在導航列中添加分類管理的連結 -->
<li><NuxtLink to="/categories">分類管理</NuxtLink></li>

四、測試與驗證

現在,我們已經完成了分類列表頁面和新增/編輯頁面的開發。讓我們進行測試,確保功能正常運作。

1. 測試分類列表頁面

  • 登入應用程式,點擊導航列中的「分類管理」連結。
  • 應該看到分類列表,如果尚無分類,列表為空。
  • 確認「新增分類」按鈕可以正常使用。

2. 測試新增分類

  • 點擊「新增分類」按鈕,進入新增頁面。
  • 填寫表單,例如:
    • 分類名稱:薪資
    • 類型:收入
  • 提交表單,應該返回分類列表,並顯示新添加的分類。

3. 測試編輯分類

  • 在分類列表中,點擊某個分類的「編輯」按鈕。
  • 應該進入編輯頁面,表單中已填入該分類的資料。
  • 修改分類名稱或類型,提交表單,確認列表中的資料已更新。

4. 測試刪除分類

  • 在分類列表中,點擊某個分類的「刪除」按鈕。
  • 應該彈出確認對話框,確認後該分類從列表中移除。

5. 測試權限保護

  • 登出應用程式,嘗試直接訪問 /categories,應該被重導向到登入頁面。

五、實作建議

  • 統一的開發模式:延續銀行帳戶管理的開發模式,統一代碼風格和結構,提升可維護性。
  • 共用元件:善用共用元件,減少重複程式碼。
  • 錯誤處理:處理好各種錯誤情況,提供清晰的錯誤訊息,提升使用者體驗。
  • 資料驗證:確保前端與後端的驗證規則一致,避免不必要的錯誤。

小結

今天,我們成功地實作了分類列表頁面以及新增/編輯頁面。透過這次的開發,我們學習了:

  • 如何在 Nuxt 中建立頁面和元件,並使用動態路由。
  • 如何與後端 API 互動,處理分類的資料取得和提交。
  • 如何處理表單驗證和錯誤訊息,提升使用者體驗。

希望這篇文章能夠對你有所幫助,讓我們一起繼續學習和進步,打造出更加完善的應用程式!


感謝你的閱讀,如果你有任何問題或建議,歡迎在下方留言討論。我們下次見!

這是一系列以軟體開發為主題的輕鬆分享,內容涵蓋了技術選擇、開發經驗、實戰應用等多方面的議題。無論是如何在眾多框架中做出選擇,還是如何應對技術轉移的挑戰,這裡有幽默、有趣的對話風格,將複雜的技術問題轉化為易懂的故事。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
CodeIgniter 3 和 Laravel 是兩種不同的 PHP 框架,各有其特點和適用場景。CodeIgniter 3 是一個輕量級框架,Laravel 是一個功能強大的現代 PHP 框架,同樣都有Models的它們有什麼樣的差別呢?
本篇文章為Laravel初學者提供了一個指南,深入探討了Laravel的routes目錄下的功能。文章詳細描述了web.php和api.php的差異和使用情境,並簡要介紹了console.php和channels.php的功能。透過這篇文章,讀者可以更好地理解和利用Laravel的路由功能。
Laravel框架中的路由系統是其核心功能之一,它允許開發者輕鬆地定義應用程式的URL結構和相應的邏輯。本篇文章將深入探討Laravel路由的基本概念、進階功能以及實際應用。
在Laravel的MVC架構中,視圖(View)是呈現資料給使用者的關鍵部分。本篇深入探討了視圖的基本概念、建立與管理、與資料的互動方式,以及Blade模板引擎的應用。Blade提供了一套強大的工具,使動態視圖建立更為高效。
本篇深入探討了Model的基本定義、其Controller的關係,以及如何在Controller中使用Model進行CRUD操作。強調了Model的關聯方法,如hasMany,並透過範例程式碼展示了其實際應用。為初學者提供了一個清晰的Laravel入門路徑,同時也為有經驗的開發者提供了實用的參考。
Laravel的Model是資料和邏輯的核心連接,簡化資料庫操作。本指南著重於Model的基本屬性、方法和Eloquent ORM的使用。我們詳細探討了hasMany、hasOne和belongsTo這些關聯,它們基於外鍵確定資料間的關係。透過本文,您將深入了解如何有效地在Laravel中使用Mod
CodeIgniter 3 和 Laravel 是兩種不同的 PHP 框架,各有其特點和適用場景。CodeIgniter 3 是一個輕量級框架,Laravel 是一個功能強大的現代 PHP 框架,同樣都有Models的它們有什麼樣的差別呢?
本篇文章為Laravel初學者提供了一個指南,深入探討了Laravel的routes目錄下的功能。文章詳細描述了web.php和api.php的差異和使用情境,並簡要介紹了console.php和channels.php的功能。透過這篇文章,讀者可以更好地理解和利用Laravel的路由功能。
Laravel框架中的路由系統是其核心功能之一,它允許開發者輕鬆地定義應用程式的URL結構和相應的邏輯。本篇文章將深入探討Laravel路由的基本概念、進階功能以及實際應用。
在Laravel的MVC架構中,視圖(View)是呈現資料給使用者的關鍵部分。本篇深入探討了視圖的基本概念、建立與管理、與資料的互動方式,以及Blade模板引擎的應用。Blade提供了一套強大的工具,使動態視圖建立更為高效。
本篇深入探討了Model的基本定義、其Controller的關係,以及如何在Controller中使用Model進行CRUD操作。強調了Model的關聯方法,如hasMany,並透過範例程式碼展示了其實際應用。為初學者提供了一個清晰的Laravel入門路徑,同時也為有經驗的開發者提供了實用的參考。
Laravel的Model是資料和邏輯的核心連接,簡化資料庫操作。本指南著重於Model的基本屬性、方法和Eloquent ORM的使用。我們詳細探討了hasMany、hasOne和belongsTo這些關聯,它們基於外鍵確定資料間的關係。透過本文,您將深入了解如何有效地在Laravel中使用Mod
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
在本章節中,我們探討了 PHP 中如何引用和管理套件。學習了如何使用 Composer 來安裝第三方套件,以及如何引用自定義模組。此外,我們還介紹了如何創建和使用自定義套件,並列舉了一些在 PHP 社群中常見且廣泛使用的套件和庫。通過掌握這些知識,開發者可以更有效地管理和利用各種資源。
Thumbnail
這一章節旨在介紹 PHP 中的物件導向編程(OOP)概念。通過詳細講解類別、建構子、訪問修飾符(公開、私有、受保護)、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等概念,使讀者能夠理解和應用這些 OOP 技術來編寫更具結構性和可維護性的 PHP 代碼。
Thumbnail
在這一章中,我們探討了 PHP 中的函數,包括函數的基本結構、不同的函數定義方式(如函數聲明、函數表達式、箭頭函數和匿名函數)以及如何呼叫函數。我們還討論了函數的參數處理方式,包括單個參數、多個參數、預設參數值和剩餘參數。此外,我們還介紹了函數的返回值,包括返回單個值、返回物件和返回函數的情況。
Thumbnail
本章節旨在介紹如何在不同操作系統上安裝和配置PHP環境,並使用命令行工具進行基礎操作。此外,還介紹了使用Visual Studio Code進行PHP開發的步驟,包括安裝擴展和設置調試環境。
Thumbnail
在本節中,我們介紹了PHP的基本語法,包括如何在HTML中嵌入PHP代碼,PHP腳本的執行順序,以及多種註解方式。我們還學習了如何定義和使用變數,包括單個變數和多個變數的賦值方法。這些基礎知識將幫助你開始使用PHP進行Web開發。
Thumbnail
這個章節介紹了PHP的基本特性和應用領域,並且列舉了使用PHP的知名公司和網站。了解PHP的簡單易學、跨平台、嵌入HTML等特性,以及PHP在動態網站、電子商務、內容管理系統、社交媒體平台、數據庫管理和API開發中的應用。
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
PHP(Hypertext Preprocessor)是一種流行的開源腳本語言,特別適用於網頁開發。它具有簡單的語法和易於理解的程式碼結構,並且支持多種數據庫系統和其他技術和框架集成。本文將介紹PHP的主要特點和廣泛應用性。
Thumbnail
前幾篇討論到各種裝飾器的用法,本文將介紹另外一種裝飾器,可以將方法轉換成屬性來使用。 property也可以動態的取出物件的值,隨著時間或其他運算改變所產生的值,讓我們繼續往下看更多介紹吧。
Thumbnail
PHP是一個功能豐富且靈活的語言,用於開發動態和互動性強的網站。本文介紹了PHP的主要功能和用途,以及它的優點和特性。不論你是一個初學者還是一個專業的開發人員,PHP都是一個值得學習和使用的強大工具。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
在本章節中,我們探討了 PHP 中如何引用和管理套件。學習了如何使用 Composer 來安裝第三方套件,以及如何引用自定義模組。此外,我們還介紹了如何創建和使用自定義套件,並列舉了一些在 PHP 社群中常見且廣泛使用的套件和庫。通過掌握這些知識,開發者可以更有效地管理和利用各種資源。
Thumbnail
這一章節旨在介紹 PHP 中的物件導向編程(OOP)概念。通過詳細講解類別、建構子、訪問修飾符(公開、私有、受保護)、繼承、多型、封裝、介面、抽象類別、靜態類別、列舉、委派、Lambda 表達式、泛型和反射等概念,使讀者能夠理解和應用這些 OOP 技術來編寫更具結構性和可維護性的 PHP 代碼。
Thumbnail
在這一章中,我們探討了 PHP 中的函數,包括函數的基本結構、不同的函數定義方式(如函數聲明、函數表達式、箭頭函數和匿名函數)以及如何呼叫函數。我們還討論了函數的參數處理方式,包括單個參數、多個參數、預設參數值和剩餘參數。此外,我們還介紹了函數的返回值,包括返回單個值、返回物件和返回函數的情況。
Thumbnail
本章節旨在介紹如何在不同操作系統上安裝和配置PHP環境,並使用命令行工具進行基礎操作。此外,還介紹了使用Visual Studio Code進行PHP開發的步驟,包括安裝擴展和設置調試環境。
Thumbnail
在本節中,我們介紹了PHP的基本語法,包括如何在HTML中嵌入PHP代碼,PHP腳本的執行順序,以及多種註解方式。我們還學習了如何定義和使用變數,包括單個變數和多個變數的賦值方法。這些基礎知識將幫助你開始使用PHP進行Web開發。
Thumbnail
這個章節介紹了PHP的基本特性和應用領域,並且列舉了使用PHP的知名公司和網站。了解PHP的簡單易學、跨平台、嵌入HTML等特性,以及PHP在動態網站、電子商務、內容管理系統、社交媒體平台、數據庫管理和API開發中的應用。
setter和getter能把狀態改變時需做的事情包裝起來,讓外部只需簡單修改參數就能達到預想的效果
PHP(Hypertext Preprocessor)是一種流行的開源腳本語言,特別適用於網頁開發。它具有簡單的語法和易於理解的程式碼結構,並且支持多種數據庫系統和其他技術和框架集成。本文將介紹PHP的主要特點和廣泛應用性。
Thumbnail
前幾篇討論到各種裝飾器的用法,本文將介紹另外一種裝飾器,可以將方法轉換成屬性來使用。 property也可以動態的取出物件的值,隨著時間或其他運算改變所產生的值,讓我們繼續往下看更多介紹吧。
Thumbnail
PHP是一個功能豐富且靈活的語言,用於開發動態和互動性強的網站。本文介紹了PHP的主要功能和用途,以及它的優點和特性。不論你是一個初學者還是一個專業的開發人員,PHP都是一個值得學習和使用的強大工具。