使用 Alpine.js 和 Django 動態管理留言按鈕啟用狀態

更新日期: 2024 年 12 月 1 日

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-datax-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>

代碼蓋覽

  1. x-data:定義一個局部狀態 { content: '' },用於管理輸入框的值。
  2. x-model="content":雙向綁定輸入框內容與 content 狀態。
  3. :disabled:根據 content.trim() 的值動態設定按鈕的 disabled 屬性。

x-data 的功能與運作機制

定義

  • x-data 用於在 HTML 元素上,綁定一個 Alpine.js 元件範圍,初始化並管理該元素的狀態。
  • 元件的狀態(數據)定義在 app.js 中,並通過 Alpine.data 註冊。

運作機制

  1. 設置元件範圍
    • 在表單標籤上使用 x-data="comment_form",將這段表單的邏輯,綁定到一個名為 comment_form 的 Alpine.js 元件。
    • Alpine.js 在初始化時,會自動尋找與該名稱對應的邏輯定義,並將數據綁定到該範圍內的元素。
  2. 提供數據狀態
    • 例如,在 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 定義的數據屬性之間建立聯繫。

運作機制

  1. 數據同步
    • 當輸入框的值發生變化時(例如用戶輸入文字),x-model="content" 會自動更新 comment_formcontent 屬性。
    • 反之,如果 JavaScript 中的 content 值發生變化,HTML 的輸入框也會自動更新,保持同步。
  2. 觸發交互邏輯
    • 基於 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 的邏輯中直接訪問該元素。

運作機制

  1. 設置引用
    • 在按鈕元素上使用 x-ref="btn",為該按鈕設定引用名稱 btn
    • 在 Alpine.js 中,可以通過 $refs.btn 來訪問該按鈕,進一步操作其屬性(例如移除 disabled 屬性)。
  2. 操作 DOM
    • 使用 $refs 可以簡化 DOM 操作,無需傳統的 document.querySelectorgetElementById

代碼示例

<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-datax-model 建立雙向綁定。
  • 利用 x-ref 初始化按鈕狀態。
  • 模組化元件邏輯,讓代碼更具可維護性。

希望這篇教學能幫助您在實際項目中靈活運用 Django 和 Alpine.js!

Similar Posts

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *