I am trying to implement nested models, here is the route file entry:
resources :projects do resources :instances end
Following is the snippet for project controller:
# GET /projects/new def new @project = Project.new @project.instances.build end
and project's form view:
<%= simple_form_for(@project) do |f| %> ... <%= label_tag :instance_count, "Instance Count" %> <%= select_tag :instance_count, options_for_select([0, 1, 2, 3, 4, 5], 0) %> ... <% end %>
Now when I change the number of instance count, I need to display instance fields those many times below the above form. Here is the partial code for that:
<%= form.simple_fields_for :instances do |i| %> ... <% end %>
Basically I need to call <%= render 'instances/form', form: f %>
from project's javascript file. It should work like link with remote: true
option. But in this case there is no link, but on change event the form need to be displayed. How should I implement this?
5 Answers
Answers 1
You have to once call serverside code because instances/form
contains code that can only be rendered on serverside.
First you have to do ajax call(ex. instance_new_path) and then you have to render the form on that view(instance_new.js.erb
).
example .js.erb
$("#new_form").html("<%= escape_javascript(render partial: 'instances/form' ) %>");
Answers 2
Standard is to make a partial called app/views/instances/_instance_fields.html.erb
. Then you can just load it into your form and make it hidden.
<%= simple_form_for(@project) do |f| %> <%= render 'instances/_instance_fields %> <% end %>
Cover _instance_fields
partial with some kind of container, like <fieldset class='instance_fields' style='display:none'>
. Also, you shouldn't use form object there, just go with text_field_tag/checkbox_tag inputs there. Then when you need to add more instances you just copy this hidden snippets as much times, as you need and setup proper names for inputs (to be accaptable for accepts_nested_attributes_for
).
Ping me to provide more details and assistance. This is an approach that was used in real project. Fire ajax call every time you need to add more instances is not optimized at all.
Answers 3
I suggest you to use https://github.com/nathanvda/cocoon
Or you can use similar aproach: render partial in initial form (with display:none), then remove and save partial fields with js and clone them to form when selector is hit.
Answers 4
Create a .js
file, and load it inside projects/new.html.erb
, which will execute whenever there is a change in select
value and creates a post
request to instances/new
controller which will render instances/new.js.erb
every time it is hit.
# GET /instances/new def new @f = Instance.new end
instances/new.js.erb
$('#instance-form-wrapper').append(<% escape_javascript(render 'instances/form', form: @f) %>
load.js
$(document).on('change', 'select#some-id-name', function(){ var v = $(this).val(); $('#instance-form-wrapper').html('') ; while(v--) $.post('/instances/'); })
Though you should not use like this. Rather load one instance
field already in your code, keep it hidden, as you already have instance
available in your project
. Also, you do not need any new data every time when you render it. Simply on selection of value 1 you can show
your instance
field and if the value is > 1
you can use clone
to copy it further.
Answers 5
Just use gem https://github.com/nathanvda/cocoon for the nested forms
0 comments:
Post a Comment