Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
276 views
in Technique[技术] by (71.8m points)

javascript - Rails + StimulusJS dynamically created select menu doesn't work

I'm dynamically adding fields to my form. In case of a standard text field it works fine with Rails + StimulusJS with an <template> element.

I'm using MaterializeCSS for styling and if I try to do the same thing with a select menu, it breaks and it seems the innerHTML I get back in my JS code doesn't match the code inside the template-tag. So I decided to use a div instead which I duplicate.

The view code (the relevant part):

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

This is the template I duplicte in my Stimulus controller.

This is what the first (and working) select menu looks like in HTML:

enter image description here

So the next step was to change the ID'S of the <ul> and the two <li> elements + the data-target element to target the right select menu.

What I ended up was this JS-Code, which is indeed adding a second select menu with the right styles, but it is not clickable and doesn't show options, despite they exist in the HTML markup and the ID's differ from the first one:

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)
    } 

Now it looks like this and I can't figure out how to make this thing working:

enter image description here

question from:https://stackoverflow.com/questions/65641789/rails-stimulusjs-dynamically-created-select-menu-doesnt-work

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

We're using the same stack (Rails, Stimulus.js, Materialize) with no problem. One thing you have to do after updating the select is re-initialize the Materialize select. For example, this is a general purpose nested select controller in which different sub-selects become active based on the parent select:

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);
    });
  }
}

And here is the corresponding 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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...