Question

I would like to set the value of field inside fields_for with Cocoon gem using Jquery. I am using change event on jquery.

_form

<%= form_for(@invoice) do |f| %>

  <div class="field">
    <%= f.label :total_order %><br>
    <%= f.number_field :total_order %>
    <%= f.object_id %>
  </div>
  <div id="items">
    <%= f.fields_for :items do |i| %>
      <%= render 'item_fields', :f => i %>
    <% end %>
    <div class="links">
      <%= link_to_add_association '+ produk', f, :items %>
    </div>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

_item_fields

<div class="nested-fields">
<tr>
    <td><%= f.select :product_id,
                        Product.all.collect {|p| [p.name, p.id, 
                        {'data-unit_cost'=>p.unit_cost}]}, 
                        { include_blank: true },
                        { class: "product-select"} %>
    </td>
    <td><%= f.number_field :unit_cost, 
                    label: false,
                class: "cost-input" %>
    </td> 
    <td><%= f.number_field :quantity,
                    label: false,
                    class: "qty-input" %>
    </td>
    <td style="vertical-align: top;"><%= link_to_remove_association '- remove', f %></td>
</tr>
</div>

coffee script

$("#items").on "cocoon:after-insert", ->
    $(".product-select").change ->
        $(".cost-input").val($(".product-select :selected").data("unit_cost"))

The thing is, it only works for first nested record. This might be related to dynamic id produce by fields_for but I don't know how to deal with it.

Any help would be appreciated.


Change has been made to the script and this is answer to my question.

$("#items").on "change", ".product-select", ->
    product_select = $(this)
    product_select.parent().find('.cost-input').val(product_select.find(':selected').data('unit_cost'))

Thanks to nathanvda for helping me.

Was it helpful?

Solution

You use an element ID. It is supposed unique in a HTML page. You should be using classes instead.

[UPDATE] Ok. You use global selectors, so you change all elements that have the class.

What you actually want, I guess, is change the elements that were just inserted. As shown in the documentation, this is possible. Just write

$("#items").on "cocoon:after-insert", (e, added_item) -> 
  added_item.find(".product-select").change ->
    $(this).parent().find(".cost-input").val($(this).selected.data("unit_cost"))

This code is not tested, but what I do: attach the change event. In the change event, use $(this), which points to the container triggering the event, and use that as a relative point to find the wanted item.

Please note that this is way easier to solve, if you just use jquery.

$('#items").on "change", ".product-select", ->
  product_select = $(this)
  product_select.parent().find('.cost_input').val(product_select.selected().data("unit_cost"))

This will capture all change events, inside #items that happen on a .product-select element. Which is dynamic, so it will work for newly added items as well. You might need to fiddle with the jquery a little, to find the selected value. As I said: untested code, but I hope you get the drift.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top