Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Nested remote form doesn't work on page load

I have a Rails app in which I have a form that looks something like this:

[ Parent list item 1 ]
[ Parent list item 2 ]
[ Parent list item 3 - expanded ]
    [ Child list item 1 ]
    Child inline input       Child submit button
    ------------------

[Parent input]
Parent submit button

The parent entity input always works. It is a remote form, using remote: true. When I add a parent object it gets automatically added to the list with the other parent objects. Each parent can have many children, they are displayed and listed when the user expands the corresponding parent list item (like the example above). Users can add more children by entering a value in the Child inline input, this form is also using remote: true.

The problem I'm having is that add children element doesn't always work on the first page load. It works however if I refresh the page. I'm having a hard time to understand why this is.

When I create a parent object the following js.erb is rendered:

# screen_table_id is the list with parent objects.
# localized_strings/localized_string is the tr with the object
$("#screen_table_<%= @localized_string.screen.id %>").append("<%= j render   partial: 'localized_strings/localized_string', locals: { screen:  @localized_string.screen, localized_string: @localized_string }  %>");

# I use the best in place gem to manage inline editing
jQuery('.best_in_place').best_in_place()

The relevant parts of localized_strings/localized_string looks like this:

%tbody{ id: "localized_string_parent_#{localized_string.id}"}
  %tr
    %td.expandable-column
      Clicking this reveals the child objects

/ The list of children is initially hidden
%tbody.hidden[localized_string]

  - if localized_string.translations.any?
    / Renders the children
  %tr
    / This form doesn't work on page load, after I have added the parent
    = render "translations/inline_form", app: localized_string.screen.app,  screen: localized_string.screen, localized_string: localized_string, translation:  localized_string.translations.build

And translations/inline_form looks like this:

= form_for [app, screen, localized_string, translation], remote: true do |f|
  %td{ colspan: 2 }
    .inline-form-group
      = f.text_field :value, class: "form-control inline-form-control",  placeholder: "Translation value", id: "localized_string_input_# {localized_string.id}"

  %td
    / Sometimes nothing happens when I click Submit.
    = f.submit 'Add translation', class: "btn ban-success-outline"

The faulty flow looks like this:

  1. Page load and I create a parent object (LocalizedString)
  2. It gets added to the list correctly.
  3. Expanding the new parent list element works as expected.
  4. When clicking on the submit button for the child (Translation) does nothing.

Hope my question is understandable. Please comment if you have any comments or need clarification. I'm tankful for all ideas.

like image 836
Anders Avatar asked Mar 21 '16 20:03

Anders


2 Answers

Ryan Bates did a great Railscast on this topic Nested Model Form Part 2. There are many interacting dependencies depending on your routes and model associations, but this RailsCast looks to be directly applicable.

like image 107
Dan Crews Avatar answered Oct 19 '22 03:10

Dan Crews


I'm pretty sure that my issue was caused by invalid HTML. I previously rendered the form inside the tr tag, like this:

%tr
  = render "translations/inline_form", app: localized_string.screen.app,   screen: localized_string.screen, localized_string: localized_string, translation:   localized_string.translations.build

And the inline_form started with the form itself. Instead of doing like that I instead tried to wrap it inside a td tag, like this:

# inline_form.html.haml
%td{ colspan: 4 }
  # the form wasn't previously inside a td tag.
  = form_for [app, screen, localized_string, translation], remote: true,  style: "margin-bottom: 0" do |f|

I haven't seen this problem again after this. But I'm not 100% sure that it is the solution, since the problem showed up somewhat randomly.

like image 1
Anders Avatar answered Oct 19 '22 04:10

Anders