使用 Alpine.js 和 Django 動態管理留言按鈕啟用狀態
更新日期: 2024 年 12 月 1 日
本文為 Django 會員系統建立教學,第 7 篇:
- 設計登入與註冊功能的基礎路由與頁面配置
- Django 使用者密碼加密方式詳解
- 使用 Django 內建功能實現使用者註冊與登入
- 使用 Django 實現安全登出功能:完整指南
- Django 使用者登入與資料操作的最佳實踐
- Django: 添加公開留言與履歷列表功能
- 使用 Alpine.js 和 Django 動態管理留言按鈕啟用狀態 👈 所在位置
- Django 收藏功能的實現:使用 ManyToMany 關係與自定義中介模型
建議閱讀本文前,先閱讀完 Django 與前端框架教學 系列文
Alpine.js 是一個輕量級 JavaScript 框架,可以用於簡化前端交互邏輯,讓 HTML 更具動態性。
在此教學中,我們將學習如何結合 Django 與 Alpine.js,實現留言功能的動態管理。
當輸入框有內容時,啟用「新增留言」按鈕;當輸入框為空時,按鈕將保持禁用狀態。
實現留言功能的初始模板
以下為我們的 Django 模板初始狀態,其中「新增留言」按鈕預設為禁用:
Django 模板代碼
檔案位置:templates/resumes/show.html
{% extends "shared/layout.html" %}
{% block "content" %}
<h1>{{ resume.title }}</h1>
<h3>{{ resume.skill }}</h3>
<article>
<p>{{ resume.content }}</p>
</article>
<footer>
<a href="{% url 'resumes:edit' resume.id %}" class="btn btn-sm">編輯</a>
<a href="{% url 'resumes:delete' resume.id %}" class="btn btn-sm">刪除</a>
</footer>
<section>
<form class="flex flex-col gap-2"
hx-target="#comment-list"
hx-swap="afterbegin"
hx-post="{% url 'resumes:comments' resume.id %}">
{% csrf_token %}
<div class="form-control">
<textarea name="content" class="textarea textarea-bordered"></textarea>
</div>
<div>
<button disabled class="btn btn-md btn-primary">新增留言</button>
</div>
</form>
</section>
<ul id="comment-list">
{% for comment in comments %}
{% include "comments/_comment.html" with comment=comment %}
{% endfor %}
</ul>
{% endblock %}
引入 Alpine.js 並設置雙向綁定
我們將利用 Alpine.js 實現留言按鈕的動態啟用功能。具體步驟如下:
安裝 Alpine.js
在專案中安裝 Alpine.js:
npm install alpinejs
初始化 Alpine.js
在 frontend/scripts/app.js
中引入 Alpine.js 並進行初始化:
import Alpine from "alpinejs";
window.Alpine = Alpine;
Alpine.start();
在模板中啟用 Alpine.js
利用 x-data
和 x-model
屬性,建立雙向綁定:
<section>
<form class="flex flex-col gap-2"
x-data="comment_form"
hx-target="#comment-list"
hx-swap="afterbegin"
hx-post="{% url 'resumes:comments' resume.id %}">
{% csrf_token %}
<div class="form-control">
<textarea x-model="content" name="content" class="textarea textarea-bordered"></textarea>
</div>
<div>
<button x-ref="btn" class="btn btn-md btn-primary">新增留言</button>
</div>
</form>
</section>
代碼蓋覽
x-data
:定義一個局部狀態{ content: '' }
,用於管理輸入框的值。x-model="content"
:雙向綁定輸入框內容與content
狀態。:disabled
:根據content.trim()
的值動態設定按鈕的disabled
屬性。
x-data
的功能與運作機制
定義
x-data
用於在 HTML 元素上,綁定一個 Alpine.js 元件範圍,初始化並管理該元素的狀態。- 元件的狀態(數據)定義在
app.js
中,並通過Alpine.data
註冊。
運作機制
- 設置元件範圍
- 在表單標籤上使用
x-data="comment_form"
,將這段表單的邏輯,綁定到一個名為comment_form
的 Alpine.js 元件。 - Alpine.js 在初始化時,會自動尋找與該名稱對應的邏輯定義,並將數據綁定到該範圍內的元素。
- 在表單標籤上使用
- 提供數據狀態
- 例如,在
app.js
中定義的comment_form
包含一個content
屬性(對應輸入框的值),其初始值為空字串。
- 例如,在
代碼示例
<form x-data="comment_form">
...
</form>
// app.js
import "htmx.org";
import Alpine from "alpinejs";
Alpine.data("comment_form", () => ({
}));
Alpine.start();
x-model
的功能與運作機制
定義
x-model
用於 雙向綁定數據,即在 HTML 元素(如輸入框)的值和 Alpine.js 定義的數據屬性之間建立聯繫。
運作機制
- 數據同步
- 當輸入框的值發生變化時(例如用戶輸入文字),
x-model="content"
會自動更新comment_form
的content
屬性。 - 反之,如果 JavaScript 中的
content
值發生變化,HTML 的輸入框也會自動更新,保持同步。
- 當輸入框的值發生變化時(例如用戶輸入文字),
- 觸發交互邏輯
- 基於
content
的值,可以執行特定的交互邏輯,例如:當content
有內容時啟用按鈕。
- 基於
代碼示例
<textarea x-model="content" name="content" class="textarea textarea-bordered"></textarea>
// app.js
import "htmx.org";
import Alpine from "alpinejs";
Alpine.data("comment_form", () => ({
content: "", // 初始化數據
}));
Alpine.start();
x-ref
的功能與運作機制
定義
x-ref
用於給 HTML 元素指定一個引用名稱,便於在 Alpine.js 的邏輯中直接訪問該元素。
運作機制
- 設置引用
- 在按鈕元素上使用
x-ref="btn"
,為該按鈕設定引用名稱btn
。 - 在 Alpine.js 中,可以通過
$refs.btn
來訪問該按鈕,進一步操作其屬性(例如移除disabled
屬性)。
- 在按鈕元素上使用
- 操作 DOM
- 使用
$refs
可以簡化 DOM 操作,無需傳統的document.querySelector
或getElementById
。
- 使用
代碼示例
<button x-ref="btn" class="btn btn-md btn-primary" disabled>新增留言</button>
Alpine.data("comment_form", () => ({
content: "", // 初始化數據
init() {
// 監聽輸入框的變化,當有內容時啟用按鈕
this.$watch("content", (value) => {
if (value.trim() === "") {
this.$refs.btn.setAttribute("disabled", true);
} else {
this.$refs.btn.removeAttribute("disabled");
}
});
},
}));
三者聯動的工作原理
初始化階段
- 當網頁加載時,
x-data="comment_form"
將觸發 Alpine.js 初始化,設置表單範圍並綁定content
屬性到輸入框。
用戶輸入階段
- 當用戶在文本框中輸入內容時,
x-model="content"
自動更新content
的值。
按鈕狀態控制
- 透過
$watch
,Alpine.js 實時監控content
的值。如果content
有內容,移除按鈕的disabled
屬性,否則添加disabled
。
完整代碼示例
HTML
<form x-data="comment_form" hx-target="#comment-list" hx-swap="afterbegin" hx-post="{% url 'resumes:comments' resume.id %}">
{% csrf_token %}
<div class="form-control">
<textarea x-model="content" name="content" class="textarea textarea-bordered"></textarea>
</div>
<div>
<button x-ref="btn" class="btn btn-md btn-primary" disabled>新增留言</button>
</div>
</form>
JavaScript (app.js
)
import "htmx.org";
import Alpine from "alpinejs";
Alpine.data("comment_form", () => ({
content: "", // 初始化內容為空
init() {
// 實時監控 content 的值,根據條件控制按鈕狀態
this.$watch("content", (value) => {
if (value.trim() === "") {
this.$refs.btn.setAttribute("disabled", true);
} else {
this.$refs.btn.removeAttribute("disabled");
}
});
},
}));
Alpine.start();
總結
通過結合 Django 與 Alpine.js,我們成功實現了留言按鈕的動態啟用功能:
- 使用
x-data
和x-model
建立雙向綁定。 - 利用
x-ref
初始化按鈕狀態。 - 模組化元件邏輯,讓代碼更具可維護性。
希望這篇教學能幫助您在實際項目中靈活運用 Django 和 Alpine.js!