hotwiredstimulus 和 hotwiredturbo-rails 实现像element-plus 一样的多级Cascader 级联选择器
首先,需要安装 @hotwired/stimulus 和 @hotwired/turbo-rails。
然后,按照以下步骤实现多级Cascader级联选择器:
-
创建一个 Stimulus 控制器,命名为 CascaderController。
-
在 CascaderController 控制器中,定义一个 initialize 方法,用于初始化 Cascader。
-
在 initialize 方法中,获取 Cascader 的数据源,并将数据源保存在控制器的属性中。
-
在 initialize 方法中,获取 Cascader 的初始值,并将初始值保存在控制器的属性中。
-
在 initialize 方法中,根据数据源和初始值,生成 Cascader 的 HTML。
-
在 Cascader 的 HTML 中,定义多个 select 元素,用于选择 Cascader 的不同级别。
-
在 Cascader 的 HTML 中,为每个 select 元素添加 change 事件监听器,用于更新 Cascader 的值。
-
在 CascaderController 控制器中,定义一个 update 方法,用于更新 Cascader 的值。
-
在 update 方法中,根据当前选择的值,更新 Cascader 的下一级别的选项。
-
在 CascaderController 控制器中,定义一个 submit 方法,用于提交 Cascader 的值。
-
在 submit 方法中,将 Cascader 的值提交到服务器端。
-
在服务器端,根据 Cascader 的值,返回相应的数据。
-
在服务器端,将返回的数据转换为 JSON 格式,并将其返回给客户端。
-
在客户端,根据返回的数据,更新 Cascader 的下一级别的选项。
-
在客户端,重复步骤 10 到步骤 14,直到 Cascader 的值被提交到服务器端。
下面是一个示例 CascaderController 控制器的代码:
import { Controller } from "@hotwired/stimulus";
import { Turbo } from "@hotwired/turbo-rails";
export default class extends Controller {
static targets = ["select"];
initialize() {
this.data = JSON.parse(this.element.dataset.data);
this.value = JSON.parse(this.element.dataset.value);
let html = "";
let values = this.value;
for (let i = 0; i < this.data.length; i++) {
let options = "";
let selected = values[i] || "";
for (let j = 0; j < this.data[i].length; j++) {
let option = this.data[i][j];
let text = option.text;
let value = option.value;
let attrs = option.attrs || {};
attrs.value = value;
if (value == selected) {
attrs.selected = "selected";
}
let attrsString = Object.keys(attrs)
.map(key => `${key}="${attrs[key]}"`)
.join(" ");
options += `<option ${attrsString}>${text}</option>`;
}
html += `<select data-cascader-target="select" data-cascader-level="${i}">${options}</select>`;
}
this.element.innerHTML = html;
}
update(event) {
let select = event.target;
let level = parseInt(select.dataset.cascaderLevel);
let value = select.value;
this.value[level] = value;
for (let i = level + 1; i < this.selectTargets.length; i++) {
let select = this.selectTargets[i];
let options = Array.from(select.options);
options.forEach(option => {
let attrs = option.dataset.attrs ? JSON.parse(option.dataset.attrs) : {};
let disabled = attrs.disabled;
if (disabled) {
option.disabled = true;
} else {
option.disabled = false;
option.selected = false;
}
});
}
if (value) {
let url = this.element.dataset.url.replace(":value", JSON.stringify(this.value));
Turbo.fetch(url).then(response => {
return response.json();
}).then(data => {
let options = Array.from(select.options);
options.forEach(option => {
let attrs = option.dataset.attrs ? JSON.parse(option.dataset.attrs) : {};
let value = option.value;
let disabled = attrs.disabled;
if (data[value]) {
let text = data[value].text || "";
let attrs = data[value].attrs || {};
if (disabled) {
option.disabled = false;
}
option.text = text;
attrs.value = value;
if (attrs.selected) {
option.selected = true;
}
option.dataset.attrs = JSON.stringify(attrs);
} else {
option.disabled = true;
}
});
});
} else {
for (let i = level + 1; i < this.selectTargets.length; i++) {
let select = this.selectTargets[i];
let options = Array.from(select.options);
options.forEach(option => {
let attrs = option.dataset.attrs ? JSON.parse(option.dataset.attrs) : {};
let value = option.value;
let disabled = attrs.disabled;
if (!disabled) {
option.disabled = true;
}
});
}
}
}
submit(event) {
event.preventDefault();
let form = this.element.closest("form");
let input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", this.element.getAttribute("name"));
input.setAttribute("value", JSON.stringify(this.value));
form.appendChild(input);
Turbo.visit(form.action, { method: form.method, body: new FormData(form) });
}
}
在这个示例中,我们使用了 @hotwired/stimulus 和 @hotwired/turbo-rails 的一些特性,比如数据属性、目标、事件监听器、Turbo.fetch 等。我们还定义了一个 update 方法和一个 submit 方法,用于更新 Cascader 的值和提交 Cascader 的值。在 update 方法中,我们使用了 JSON.parse 和 JSON.stringify 方法,将 Cascader 的值转换为 JSON 格式,并将 JSON 格式转换为 Cascader 的值。在 submit 方法中,我们使用了 document.createElement、input.setAttribute 和 form.appendChild 方法,创建一个隐藏的 input 元素,并将 Cascader 的值作为其值提交到服务器端。
原文地址: https://www.cveoy.top/t/topic/FwJ 著作权归作者所有。请勿转载和采集!