3

How can I add one more same set of inputs for example for education object, so I will have 2 new education objects after submitting? Preferable new set needs to be shown by clicking on icon that goes after existing set of inputs.

This is my new method:

def new
  @user = User.new
  @user.educations.build
  @user.works.build
end

And my view for it:

<%= simple_form_for [:admin, @user] do |u| %>
      <%= u.error_notification %>

      <%= u.input :name, label: "Name" %>
      <p><b>Photo</b></p>
      <%= image_tag(@user.photo_url, size: "80x90",
                    class:"img-rounded") if @user.photo? %>
      <%= u.input :photo, label: false %>
      <%= u.input :tel, label: "Tel.:" %>

      <h3>Education</h3>
      <hr>
      <%= u.simple_fields_for :educations do |e| %>
        <%= e.input :name, label: "University" %>
        <%= e.input :year_started, label: "Started" %>
        <%= e.input :year_finished, label: "Ended" %>
      <% end %>

      # icon `+`
      <i class="fa fa-plus fa-2x"></i>

      <h3>Work</h3>
      <hr>
      <%= u.simple_fields_for :works do |w| %>
        <%= w.input :name, label: "Name" %>
        <%= w.input :year_started, label: "Started" %>
        <%= w.input :year_finished, label: "Ended" %>
      <% end %>


      <%= u.button :submit, "Надіслати" %>
<% end %>

2 Answers 2

2

If you wanted to add the extra objects when you invoke the new method, you'd just need to "build" more associated objects:

def new
  @user = User.new
  2.times do
    @user.educations.build
  end
  @user.works.build
end

This would give you two sets of education fields (no more code changes required).


If you wanted to invoke the extra objects/fields after you've already rendered the new method, you'll have to do it dynamically, through, as @Tom Walpole suggested, using something like Cocoon.

There is a dated, but good tutorial here.

I've written about it too.

--

Adding fields on the fly relies on a simple pattern:

  1. Button / Icon press
  2. Ajax call to controller
  3. Controller builds form with fields_for
  4. Ajax response puts new fields_for in DOM

The main difference between this (ajax) and something like the "Railscast" (static) method is it builds the fields_for properly in rails. No hack jobs...

#app/views/admin/users/new.html.erb
<%= link_to fa-icon("plus 2x"), admin_new_user_path, remote: true %>

If you're using font-awesome, you'll be best with the font-awesome-rails gem, as you get the fa-icon helper.

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   respond_to :js, :html

   def new
     @user = User.new
     @user.educations.build
     @user.works.build unless request.xhr?
   end
end

#app/views/users/new.js.erb
var form = $("<%=j render 'users/new' ");
$("form#new_admin_user [[fields_for_identifier]]").html($(form).html());

The big trick with this is the child_index: Time.now.to_i method. The big problem with the "static" approach is that the id of each new field will be exactly the same as the last, messing up your params:

#app/views/users/new.html.erb
<% if request.xhr? %>
  <%= simple_form_for [:admin, @user] do |u| %>
      <%= u.simple_fields_for :educations, child_index: Time.now.to_i do |e| %>
         <%= e.input :name, label: "University" %>
         <%= e.input :year_started, label: "Started" %>
         <%= e.input :year_finished, label: "Ended" %>
      <% end %>
  <% end %>
<% else %>
   ... your code ...
<% end %>

The above should work, although may need tweaking.

Sign up to request clarification or add additional context in comments.

Comments

1

Easiest solution is probably the cocoon gem - https://github.com/nathanvda/cocoon

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.