问题描述
我正在向表单中动态添加字段。在标准文本字段的情况下,它适用于带有 <template>
元素的 Rails + StimulusJS。
我正在使用 MaterializeCSS 进行样式设置,如果我尝试使用选择菜单做同样的事情,它会中断,而且我在 JS 代码中返回的 innerHTML 似乎与模板标签中的代码不匹配。所以我决定使用我复制的 div 来代替。
视图代码(相关部分):
<div data-nested-form-target="template">
<%= f.fields_for :stations,department.stations.build,child_index: "NEW_RECORD" do |station| %>
<%= render "admin/departments/stations/station_fields",f: station %>
<% end %>
这是我在 Stimulus 控制器中复制的模板。
所以下一步是更改 <ul>
和两个 <li>
元素 + data-target
元素的 ID 以定位正确的选择菜单。
我最终得到的是这个 JS 代码,它确实添加了具有正确样式的第二个选择菜单,但它不可点击且不显示选项,尽管它们存在于 HTML 标记中并且 ID 与第一个:
add_association(event) {
event.preventDefault()
let random_id = this.generate_random_id()
let content = this.templateTarget.cloneNode(true)
content.getElementsByTagName("ul").item(0).setAttribute("id",random_id)
content.getElementsByClassName("dropdown-trigger").item(0).setAttribute("data-target",random_id)
let list_elements = Array.from(content.getElementsByTagName("ul").item(0).querySelectorAll("li"))
list_elements.forEach((item) => {
let rnd = this.generate_random_id()
item.setAttribute("id",rnd)
})
let html = content.innerHTML.replace(/NEW_RECORD/g,new Date().getTime())
this.linksTarget.insertAdjacentHTML("beforebegin",html)
console.log(html)
let collection = this.basicTarget.getElementsByClassName("nested-fields")
let element = collection[collection.length - 1].getElementsByClassName("animate__animated")[0]
element.classList.add(this.fadeInClass)
}
现在看起来像这样,我不知道如何使这件事起作用:
解决方法
我们使用相同的堆栈(Rails、Stimulus.js、Materialize)没有问题。更新选择后必须做的一件事是重新初始化 Materialize 选择。例如,这是一个通用的嵌套选择控制器,其中不同的子选择根据父选择变为活动状态:
import { Controller } from 'stimulus';
import Materialize from 'materialize-css';
export default class extends Controller {
static targets = [
'childSelect',]
parentSelectChanged (e) {
const selectedParentMenu = e.target.value;
this.childSelectTargets.forEach(selectElement => {
if (selectElement.dataset.parentMenuName === selectedParentMenu) {
selectElement.disabled = false;
selectElement.value = '';
} else {
selectElement.disabled = true;
}
Materialize.FormSelect.init(selectElement);
});
}
}
这里是对应的 Haml:
.input-field.col
= select_tag :category,options_for_select(grouped_conditions.keys.sort,selected_parent_menu_name),include_blank: 'Select One...',data: { action: 'nested-select#parentSelectChanged' }
.input-field.col.hide-disabled
- grouped_conditions.each do |parent_menu_name,child_conditions|
= f.select :condition_id,options_for_select(child_conditions.sort_by(&:menu_name).map{ |tc| [tc.menu_name,tc.id] },selected_condition_id),{ include_blank: 'Select One...' },disabled: selected_parent_menu_name != parent_menu_name,data: { 'nested-select-target' => 'childSelect','parent-menu-name' => parent_menu_name }
= f.label :condition_id