#javascript #ruby-on-rails #ruby #stimulusjs
#javascript #ruby-на-рельсах #рубиновый #стимуляторjs
Вопрос:
Я динамически добавляю поля в свою форму. В случае стандартного текстового поля он отлично работает с Rails StimulusJS с <template>
элементом.
Я использую MaterializeCSS для стилизации, и если я попытаюсь сделать то же самое с помощью меню выбора, оно сломается, и кажется, что innerHTML, который я получаю обратно в своем JS-коде, не соответствует коду внутри шаблона-тега. Поэтому я решил вместо этого использовать 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 %>
Это шаблон, который я дублирую в своем контроллере стимулов.
Вот как выглядит первое (и рабочее) меню выбора в HTML:
Итак, следующим шагом было изменить идентификаторы элемента <ul>
и двух <li>
элементов data-target
элемент, чтобы он был нацелен на меню выбора справа.
В итоге я получил этот JS-код, который действительно добавляет второе меню выбора с правильными стилями, но оно не доступно для просмотра и не отображает параметры, несмотря на то, что они существуют в разметке HTML, а идентификаторы отличаются от первого:
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)
}
Теперь это выглядит так, и я не могу понять, как заставить эту вещь работать:
Комментарии:
1. Можете ли вы опубликовать сгенерированный HTML-код после добавления второго поля выбора?
Ответ №1:
Мы используем тот же стек (Rails, Stimulus.js , Материализоваться) без проблем. Одна вещь, которую вам нужно сделать после обновления выбора, — это повторно инициализировать выбор 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(amp;: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
Комментарии:
1. Да, я думал, что что-то вроде повторной инициализации может это исправить, я попробую так, как вы это сделали. Честно говоря, мой следующий проект не будет использовать Materialize: D