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 %>
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:
- Button / Icon press
- Ajax call to controller
- Controller builds form with
fields_for- Ajax response puts new
fields_forin 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.
Easiest solution is probably the cocoon gem - https://github.com/nathanvda/cocoon
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With