Render partial after change select - ruby-on-rails

I have the following view
<%= form_for #survey do |f| %>
<div class="field">
<%= f.label :title %><br>
<%= f.text_field :title %> <br><br>
<%= f.label :description %><br>
<%= f.text_field :description %><br><br>
</div>
<%= f.fields_for :survey_sections do |builder| %>
<%= builder.text_field :title, :placeholder => "Abschnittsbeschreibung" %><br>
<%= builder.fields_for :questions do |quest| %>
<%= quest.text_field :text, :placeholder => "Frage" %> <br>
<%= quest.fields_for :answers do |ans| %>
<%= ans.text_field :text, :placeholder => "Antwort" %> <br>
<%end%>
<%end%>
<%= select_tag("question_type",options_for_select([["Radio", "radio"],["Checkbox", "check"]])) %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I want to render a partial in this view after selecting one of the options.
How can i do this?

Easiest way is render the partial with display:none
<div id='foo' style='display:none'>
<%= render :foobar %>
</div>
And when a user select something, show it by JS(jQuery).
$('[name=question_type]').change(function() {
$('#foo').show();
});

If you are using jQuery, then try this:
VIEW
<%= select_tag("qustion_type",options_for_select([["Radio", "radio", {:onclick => "someFunction(#{controller_path})"}],["Checkbox", "check", {:onclick => "someFunction(#{controller_path})"}]])) %>
JAVASCRIPT
function someFunction(url) {
jQuery.ajax({
url: url,
data: {some_data: "data_value"},
success: function(data) {
//data has the html code that you render in controller
}
});
}
EDIT (See Comments)
As you asked that you need to render a partial on each option select. So, for each option select you need to hit a controller method. In my example url is that controller end point(eg:- render_radio_some_controller_path).
def render_radio
render :partial => "radio"
end
After this, it will go to the success block of Ajax call and data will have the html defined in radio.html.erb. Now, you just have to use jQuery to update the desired div html with data(Eg:- jQuery("#some_div").html(data);)

Related

Rails 4 ajax load partial into view

there is a way to put an input dynamically from button?
Example:
this is the form:
<%= form_for(#order) do |f| %>
.
...
<div class="field">
<%= f.label :productlist %><br>
<%= f.select :productlist, #products, :prompt => 'Select one!' %>
<%= link_to 'Add More', '#', id: 'products-link' %>
</div>
<div id="newproduct">
<p>load here the new input on Add more link</p>
</div>
<div class="field">
<%= f.label :status %><br>
<%= f.text_field :status %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
so i thinked up to ajax and a way to load a partial input into the form, but im not understanding the correct way to do this.
Thank you
In your javascript file add:
$("a#products-link").click(function(){
$.get('/partials/products_form', function(data){
$("div#newproduct").append(data);
}, 'html');
});
Essentially what is happening is that you are going to send a get request via ajax to a form in /partials/products_form or wherever you choose to keep your form partial. And then this html will be appended to whatever div/identifier you choose in this case div#newproduct.

Extend forms without page reload, rails

I'm searching for a solution to extend my form without page reload.
First I tried to render a partial with coffee or javascript, but escape_javascript didnt work.
Here's the view
<%= form_for #recipe = current_user.recipes.build do |f| %>
<%= f.label :name, "Recipe Name" %>
<%= f.text_field :name %>
<%= button_to "Add Ingredient", '#', class: "btn btn-lg btn-primary", id: "add" %>
<p></p>
<%= f.submit class: "btn" %>
<% end %>
The form above should be extented with following partial by every click on the button
<div id="recipe-ingredients">Quantity
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= render 'quantity_fields', f: quantity %>
<% end %>
</div>
_quantity_fields
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
This approach did not work (recipes.js.erb)
$(document).ready(function() {
$("#add").click(function() {
$("p").append("<%= escape_javascript
render(:partial => 'quantities') %>");
});
});
There's a workaround (see below) but I'm searching for a better solution.
$(document).ready(function() {
$("#workout-week").append(<%= escape_javascript(
Haml::Engine.new(File.read(File.join(Rails.root,'app/views',
'_show_period.html.haml'))).render(Object.new, period: #period)) %>);
});
A second approach is to write following lines in Coffee or JavaScript:
<%= f.fields_for :quantities, #recipe.quantities.build do |quantity| %>
<%= f.label :amount, "Amount:" %>
<%= f.text_field :amount %>
<%= f.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
<% end %>
I'm a newbie so take this with a grain of salt, but have you tried using render :foo instead of redirect_to :foo in the appropriate controller function?
I solved it with cocoon
<%= form_for #recipe do |f| %>
<div class="field">
<%= f.label :name %>
<br/>
<%= f.text_field :name %>
<%= f.fields_for :quantities do |quantity| %>
<%= render 'quantity_fields', :f => quantity %>
<% end %>
<div class="links">
<%= link_to_add_association 'add', f, :quantities %>
</div>
</div>
<%= f.submit %>
<% end %>

Rails 4 - Rendering partial with access to class

I have two classes Bid (has_many :mozs) and Moz (belongs_to :bid). I am trying to render a partial for creating Moz objects.
<%= f.fields_for :mozs do |builder| %>
<%= render "moz_fields", :f => builder %>
<% end %>
in my partial:
<div class="field fields">
<%= f.label :url, "Comparative URL" %><br>
<%= f.text_field :url %>
<%= f.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
When the contents of the partial are in the fields_for tag:
<%= f.fields_for :mozs do |builder| %>
<div class="field fields">
<%= builder.label :url, "Comparative URL" %><br>
<%= builder.text_field :url %>
<%= builder.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>
then everything works fine. But I need it in a partial to dynamically add the fields. When I keep it in a partial I get this error: undefined method `url' for NilClass:Class.
I don't understand why the class would be nil just because I put it in a partial.
I think the problem will likely be with your rendering of a partial inside the fields_for tag && you're not using the locals argument:
<%= render partial: "moz_fields", locals: { f: builder } %>
#moz_fields
<%= f.fields_for :mozs do |b| %>
<div class="field fields">
<%= b.label :url, "Comparative URL" %><br>
<%= b.text_field :url %>
<%= b.hidden_field :destroy %>
<%= link_to_function "remove", "remove_fields(this)"%>
</div>
<% end %>

Nested_form_for with field_for not working

my view is
<h3> Register New Items </h3>
<div class="row">
<div class="span2 offset4">
<%= nested_form_for #item_category, :url => items_path, :method => :post, :html => { :class => "item_category"} do |f| %>
<div><%= f.label :item_name %>
<%= f.text_field :item_name %></div>
</br>
<div>
<%= f.fields_for :item_companies do |f| %>
<%= f.label :company_name %>
<%= f.text_field :company_name %>
</div>
</br>
<%= f.fields_for :item_weights do |f| %>
<div>
<%= f.label :weight %>
<%= f.text_field :weight %>
</div>
</br>
<div>
<%= f.label :price %>
<%= f.text_field :price %>
</div>
<%end%>
<%end%>
<div><%= f.submit "Submit" %></div>
<% end %>
</div>
and controller
def new
#item_category = ItemCategory.new
item_company = #item_category.item_companies.build
item_company.item_weights.build
end
and when I have applied debugger in create action and I saw value of params[:item_category] and this is generated {"item_name"=>"iname", "item_companies_attributes"=>{"0"=>{"company_name"=>"cname", "item_weights_attributes"=>{"0"=>{"weight"=>"20kg", "price"=>"100"}}}}}
ItemCategory.new(params[:item_category])
generated error
ActiveModel::MassAssignmentSecurity::Error Exception: Can't mass-assign protected attributes: item_companies_attributes.
Where i am wrong and how to save value in three tables using this.
It seems that you forgot to add this piece of code in your ItemCategory model:
attr_accessible :item_companies_attributes
which will allow you to set these attributes.

Adding javascript handlers to remote form object after injection with RJS

I have a page form, where i want the user to add nested forms by clicking on a remote link ('add photo', f. ex). Upon clicking the button I inject the nested forms with RJS. The injected forms are remote forms, but after injection the forms have no javascript events attached so they just submit with http to the controller of the nested object. Beside that, everything works fine.
My question is:
Is it possible to trigger revalidation of javascript of remote forms via RJS, after injection??
That way my nested forms would get the proper javascript event handling and submit with AJAX.
My page form (_form.html.erb):
<% javascript 'ckeditor/ckeditor' %>
<%= form_for #page, :html => { :multipart => true } do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :active %><br />
<%= f.check_box :active %>
</p>
<p>
<%= f.label :homepage %><br />
<%= f.check_box :homepage %>
</p>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.label :description %><br />
<%= f.text_area :description, :rows => 5, :cols => 80 %>
</p>
<p>
<%= f.label :text %><br />
<%= f.text_area :text, :class => 'html' %>
</p>
<p>
<%= f.label :picture_class %><br />
<%= f.select :picture_class, ['left','right','full'] %>
</p>
<% unless #page.new_record? %>
<h2>Photos</h2>
<%= link_to 'Add photo', add_photo_page_url(#page), :remote => true %>
<div id="photos">
<%= render :partial => 'shared/forms/photo', :collection => #page.photos %>
</div>
<h2>Snippets</h2>
<%= link_to 'Add snippet', add_snippet_page_url(#page), :remote => true %>
<div id="snippets">
<%= render :partial => 'shared/forms/photo', :collection => #page.snippets %>
</div>
<h2>Downloads</h2>
<%= link_to 'Add download', add_download_page_url(#page), :remote => true %>
<div id="downloads">
<%= render :partial => 'shared/forms/download', :collection => #page.downloads %>
</div>
<h2>Paragraphs</h2>
<%= link_to 'Add paragraph', add_paragraph_page_url(#page), :remote => true %>
<div id="paragraphs">
<%= render :partial => 'shared/forms/paragraph', :collection => #page.paragraphs %>
</div>
<% end %>
<p><%= f.submit %></p>
<% end %>
<%= javascript_tag 'CKEDITOR.replaceAll("html");' %>
Controller code to build the nested photo object: (page_controller.rb):
def add_photo
#page = Page.find(params[:id])
#photo = #page.photos.build
end
RJS code that gets executed by clicking 'add photo' (add_photo.js.rjs):
page.insert_html :bottom, :photos, :partial => 'shared/forms/photo', :object => #photo
page.visual_effect :highlight, :photos, :duration => 2
The partial/form that gets injected with RJS (_photo.html.erb):
<%= form_for [#page, photo], :remote => true do |f| %>
<p>
<%= f.check_box :active %>
<%= f.text_field :name %>
<%= f.file_field :photo %>
<%= f.submit 'Save' %>
</p>
<% end %>
Any help would be appreciated. I would like to solve this with nested forms (not nested attributes) and RJS, but was unable to google my way to documentation on this.
Thanks!!
-- Jakob
If you want to stick with RJS, you'll need to look into the built-in javascript to see how they're registering everything. They probably just do it on DOM ready and bind to the submit() event. It's most likely encapsulated in a method which looks for anything marked :remote => true and binds to the submit() event so it will submit via AJAX. You can execute the same logic but isolate it to your new form. So maybe your partial could have a JavaScript tag which executes that logic for that form, based on the id, or based on the classname, ignoring everything but the most recently added form.

Resources