0

Rails 7.0.0

After reading a few SO and blog posts, it's straightforward enough to submit a model form with an array param, and I've setup the new.html.erb form to use multiple: true, which works great. However, I'm finding edit action is not as simple.

By default text_field renders the content of the parameter provided to it, so providing it the array causes it to render the entire array (which makes sense, but is also the problem I want to solve for).

So, for new.html.erb I have:

  <div class="form-group">
    <%= form.label :custom_attributes %>
    <%= form.text_field :template_attributes, multiple: true, class: "form-control" %>
    <%= form.text_field :template_attributes, multiple: true, class: "form-control" %>
  </div>

And get:

new form

And after save:

irb(main):007:0> t.template_attributes
=> ["one", "two"]

But as described, edit.html.erb:

  <div class="form-group">
    <%= form.label :custom_attributes %>
    <%= form.text_field :template_attributes, multiple: :true, class: "form-control" %>
    <%= form.text_field :template_attributes, multiple: :true, class: "form-control" %>
  </div>

produces

edit form

How can I edit the array indices, dynamically?

Ideally I'd like to produce an input field for each array element, and on submit update the array indices that have changed.I’ve tried using .each on the array itself, and rendering form helpers for each indice, but have yet to find an appropriate helper method.

Jack Collins
  • 339
  • 1
  • 2
  • 13

1 Answers1

0

I decided to solve it with a stimulus controller

edit.html.erb

  <div data-controller="employee-template" data-employee-template-template="<%= @employee_template.template_attributes %>">
    <div data-employee-template-target="attributes"></div>
  </div>

app/javascript/controllers/employee_template_controller.js

import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["attributes"]

  connect() {
    const template = (this.data.get("template"))

    const parsedTemplate = template.replace("[","").replace("]","").replaceAll('"',"").split(",")
    const array = Array.from(parsedTemplate)

    const html = array.map((a) => {
        return `<div><input multiple="multiple" class="form-control" type="text" value="" name="employee_template[template_attributes][]" id="employee_template_template_attributes"placeholder=${a}></input></div>`
      })

    html.forEach(h => this.attributesTarget.innerHTML += h)

  }
}
Jack Collins
  • 339
  • 1
  • 2
  • 13