简体   繁体   中英

Rails adding dynamically nested form partial with local in JS

I am appending different inputs depending on the user's actions on my form. If the user clicks on the "list" radio button, I want to display nested inputs for possibilities . I am trying to use the cocoon gem which enables to create dynamically input fields. My form looks like this :

<%= form_for([@issue, @question]) do |f| %>
  <%= f.label :content %>
  <%= f.text_area :content%>
  <br>
  <%= f.fields_for :answer do |a| %>
    <%= a.label "Answer Type :" %>
    <br>
    <% Answer.answer_type.options.each do |option| %>
      <%= a.label option.first %>
      <%= a.radio_button :answer_type, option.first, class: "answer_type" %>
      <br>
    <% end -%>
    <div class="question_list"></div>
  <% end -%>

  <%= f.submit %>
  <ul>
    <% @question.errors.full_messages.each do |message| %>
      <li><%= message%></li>
    <% end -%>
  </ul>
<% end %>

And this is the JS displaying different partials depending on where the user clicks :

<%= content_for(:after_js) do %>
  <script>
    $(document).ready(function(){
      $(".answer_type").click(function(){
        var value = $(this).val();
        console.log(value);

        if (value == "Yes/no") {
          $(".question_list").empty();
          $(".question_list").append("<%= j render 'questions/type/yes_no' %>");
        }
        else if (value == "List") {
          $(".question_list").empty();
          $(".question_list").append("<%= j render 'questions/type/list', a:a %>");
        }
      });
    })
  </script>
<% end -%>

if the user clicks on the checkbox "list", I am displaying this partial which needs the a variable to be built:

<%= a.fields_for :possibilities do |possibility| %>
  <%= render 'possibilities/possibility_fields', a: possibility%>
    <div class="links">
      <%= link_to_add_association 'add possibility', a, :possibilities %>
    </div>
<% end -%>

Problem is the js:

 else if (value == "List") {
          $(".question_list").empty();
          $(".question_list").append("<%= j render 'questions/type/list', a:a %>");

triggers an error

undefined local variable or method `a' for #<#<Class:0x007fb5d4786568>:0x007fb5d59c2808>

because I believe a is not built yet when the JS is read.

How can I bypass this and build dynamically my nested fields when the user clicks on "list" radio button ?

There seems to be a confusion between server-side rendering and client side rendering here:

  • Server-side rendering happens inside your rails app. It's the process that turns all your erb into html and javascript.
  • Client-side rendering happens in the user's browser. It's what happens when the browser executes the javascript.

This means that you can't render any ERB with Javascript. More precisely, when your ruby app tries to render $(".question_list").append("<%= j render 'questions/type/list', a:a %>"); , it tries to render the partial right away, before sending the response to the client. Since the a variable is only defined in your <%= f.fields_for :answer do |a| %> <%= f.fields_for :answer do |a| %> block, it raises the error you see.

Bottom line is, to do some real rendering on the client side, you'll probably need a rendering library such as ReactJS.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM