Sunday, October 22, 2017

How do I implement remote: true functionality without link_to?

Leave a Comment

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

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment