scotchpasta scotchpasta - 1 month ago 4
Javascript Question

Not sure how to find correct div every time a form is dynamically generated

I have a form that has parts that are dynamically generated based on user selection and can be done so infinite times. My setup looks like: Visualizations has_many Rows, Rows has_many Panes. When you select add row to visualization a new one will pop up, and from there you can add Panes (up to 3).



<div id="rows" class="row">
<%= f.fields_for :rows do |row| %>
<%= render 'row_fields', :f => row %>
<% end %>
<div class="rowz_links">
<%= link_to_add_association "Add Row", f, :rows %>
</div>
</div>





Cocoon has this awesome callback called after-insert that allows you to manipulate the html after a row has been inserted. I'm trying to implement a foundation dropdown window in each row. To do that I need to instantiate foundation in each dynamically generated Row. On top of that, Foundation dropdown's rely on ID's to work.

So what I tried to do is this with some help:



$('#rows')
.on('cocoon:after-insert', function() {
var dropdown_id = 'dynamic_dropdown-' + $('.pane_dropdown').size();

$(this).find('.fa-plus-square').attr('data-toggle', dropdown_id);
$(this).find('.dropdown-pane').attr('id', dropdown_id);
$(this).find('.pane_dropdown').foundation();
});

<div class="nested-fields">
<div class="field">
<%= f.label :rowtitle, 'Row Title', class: "row_title" %>
<%= f.text_field :rowtitle, class: "row_title_input" %>
<div class="pane_dropdown">
<button class="fa fa-plus-square fa-2x" type="button"></button>
<div class="dropdown-pane" data-dropdown data-hover="true" data-hover-pane="true">
<%= link_to_add_association 'Add 1', f, :panes, count: 1, partial: 'one_pane_field', id: "testingpaneone" %>
<%= link_to_add_association 'Add 2', f, :panes, count: 2, partial: 'two_pane_fields', id: "testingpanetwo" %>
<%= link_to_add_association 'Add 3', f, :panes, count: 3, id: "testingpanethree" %>
</div>
</div>
</div>
</div>





Except doing this, every time a new Row is generated it finds the first "row" every time and assigns the dynamically generated ID to it. I'm not sure how to get around this..

Answer

Looks like the reason the 'first row' is being assigned the ID each time is due to the scope of $(this) in your event handler being in reference to $('#rows') (the container for all your rows)

From the docs (and adjusted to your scenario):

$('#rows').on('cocoon:after-insert', function(e, insertedItem) {
     // ... do something
});

...where e is the event and the second parameter is the inserted or
removed item. This allows you to change markup, or add
effects/animations.

So it looks like cocoon is passing the insertedItem as the second parameter to the event callback! (which sounds like the reference you are looking for)