简体   繁体   中英

How do I implement remote: true functionality without link_to?

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?

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' ) %>");

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.

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.

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.

只需使用gem https://github.com/nathanvda/cocoon作为嵌套表单

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