Rails StimulusJS динамически созданное меню выбора не работает

#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