Rails/JS button onclick to re-render partial without entering into DB - javascript

I wish to reload a partial-form with a button(Add). I'm new and don't know how to simply display fields in partial like listings one under the other as many times Add button is clicked. I can't find a relevant example. all AJAX examples mention js.erb when object is saved in DB.
<div class="panel-body">
<%= render partial: "degrees/form", :locals => { :f => f } %>
<%= f.link_to (fa_icon 'plus').to_s + " Add Another Qualification ", render(:partial => 'degrees/form', :locals => { :f => f }), class: "btn btn-primary" %>
</div>
Here, #application is the main form trying to display degree fields. Partial is simply two text-fields- one for selecting educational degree and second its detail.Here's partial
<%= f.fields_for [Degree.new], :url => { :action => "index" } do |ff| %>
<div class = "form-group" }>
<%= ff.select :level, options_for_select(Job::EDUCATION, params[:level]), include_blank: "Select Degree", class: 'span-2' %>
<%= ff.text_field :description, :class => 'span5' %>
</div>
<% ff.submit "Add Another Degree", class: 'btn btn-primary' %>

You don't necessary need to save things to pass away to .js.erb... you can just instantiate...
But if your example is precise, you are missing the remote: true flag for the link... And the partial is not defined on the link... you need to make a view responding to the ajax...
Form example
<div class="panel-body">
<%= link_to new_thing_path, remote: true do %>
<i class="fa fa-plus">
Add another qualification
<% end %>
<div class="new-things-container">
</div>
</div>
Controller answering to the ajax request
class ThingsController < ApplicationController
def new
#thing = Thing.new
respond_with #thing
end
end
View for the ajax request rendering a partial inside a specified div
//views/things/new.js.erb
$('.panel-body .new-things-controller').append("<%= render partial: 'degrees/form', locals: { thing: #thing } %>")

Related

Rails - fields_for and javascript to dynamically add and remove fields in a form (railscasts ep. 196-197)

UPDATE
Thank you for your answer.
But If I remove
for requested_role in #project.requested_roles
from the partial, then I can't access to the requested_role.role value, because I don't have the parameter X obtained from the code
for X in #projects.requested_roles
and I can't write X.role
How can I access this value without using for or .each to scroll the requested_roles of the project?
END UPDATE
I've a problem with a social network I'm developing with Ruby on Rails. I followed the railscasts 196 and 197 to create a form with fields_for and to add fields dinamically with javascript, but I have 2 major problems.
A User can create a Project and this Project must have 1+ Requested_roles.
When I open the project edit page to change the roles, if there are N requested_roles for the project, I see N*N forms to change the requested_roles. So if I have 2 requested_roles (for example Director and Producer) I see 4 select fields, Director - Producer - Director -Producer. They are repeated N times. And I can't modify them because I can have max 1 requested_role of each type. It's fine if I have only 1 requested_role (because 1x1=1)
Project.rb
class Project < ActiveRecord::Base
attr_accessible :title, :requested_roles_attributes, :video, :num_followers, :num_likes
belongs_to :user
has_many :requested_roles, dependent: :destroy
accepts_nested_attributes_for :requested_roles, :reject_if => lambda { |a| a[:ruolo].blank? }, :allow_destroy => true
Requested_role.rb
class RequestedRole < ActiveRecord::Base
attr_accessible :role, :project_id
belongs_to :project
Projects_controller.rb
class ProjectsController < ApplicationController
def new
#project= Project.new
#requested_role= #project.requested_roles.build
end
Projects/edit.html.erb
<div class="row">
<div class="span6 offset3">
<%= form_for(#project) do |f| %>
<%= render 'shared/error_messages', object: f.object%>
<%= f.label :title, "Project title" %>
<%= f.text_field :title %>
<%= f.fields_for :requested_roles do |builder| %>
ciao
<%= render 'requested_role', :f => builder %>
<% end %>
<div class="fields">
<p><%= link_to_add_fields "Add requested role", f, :requested_roles %></p>
</div>
</br>
<%= f.submit 'Apply changes', class: 'btn btn-large btn-primary' %>
<% end %>
</div>
</div>
I think that the error is in this view (Projects/edit):
<%= f.fields_for :requested_roles do |builder| %>
ciao
<%= render 'requested_role', :f => builder %>
<% end %>
this code, even without the partial, lead to a N-times repeated requested_roles. In fact, without the partial _requested_role, we have N "ciao", but we should have only one.
projects/_requested_role.html.erb
<% if #project.requested_roles.any? %>
<p>Modifica ruoli richiesti </p>
<%end%>
<%= #project.requested_roles.count %>
<% for requested_role in #project.requested_roles %>
<div class="fields">
<p>
<p>Requested role: <%= role_to_string(requested_role.role) %></p>
<%= f.label :role, "Modify role" %>
<%= f.select :role, options_for_select([["Regista",1],["Sceneggiatore", 2],["Direttore della fotografia", 3], ["Operatore",4],
["Fonico", 5], ["Montatore", 6], ["Truccatrice",7], ["Costumista",8], ["VFX Artist",9],
["Produttore", 10], ["Attore",11], ["Attrice",12], ["Grip/Runner",13]], :selected => requested_role.role) %>
<%= link_to_remove_fields "remove", f %> #dinamically remove a field
</p>
<% end %>
</div>
Can you help me please? I can't figure out where the error is. Thank you in advance.
The other problem is related to the links to dinamically delete and add requested_roles (javascript-jquery).
If I have 3 requested_roles (9 select fields instead of 3 because of the error that I mentioned before) and I delete (through link_to_remove_fields) the last one there's no problem. But if I delete the first one, the fields and even the submit button below it disappear and I can't modify the roles or submit the changes.
When I add (through link_to_add_fields) a new role and I already have, for example, 2 requested_roles (Director, Producer), when I click on the link to add the new requested_role another bug occurres. Instead of a select field to choose the role, a copy of the 2 existing select fields (Director, Producer) appears.
application_helper.rb
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
end
def link_to_add_fields(name, f, association)
new_object = f.object.class.reflect_on_association(association).klass.new
fields = f.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
render(association.to_s.singularize, :f => builder)
end
link_to_function(name, "add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")")
end
Application.js
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(link).parent().before(content.replace(regexp, new_id));
}
I can't understand what goes wrong. If you have some idea can you give me some advice? Thank you very much.
Dario
The problem is that you're iterating twice.
<%= f.fields_for :requested_roles do |builder| %>
ciao
<%= render 'requested_role', :f => builder %>
<% end %>
Will automatically repeat the requested_role partial for each requested role. That's why it shows "ciao" N times, because that's what fields_for does at render. You probably need to read the doc to understand how it works: http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
So there is no need to have
for requested_role in #project.requested_roles
in your partial. It will only repeat all requested roles each time fields_for renders it. Here's what your code should look like in your edit.html.erb :
<% if #project.requested_roles.any? %>
<p>Modifica ruoli richiesti </p>
<%end%>
<%= #project.requested_roles.count %>
<%= f.fields_for :requested_roles do |builder| %>
<%= render 'requested_role', :f => builder %>
<% end %>
<p><%= link_to_add_fields "Add requested role", f, :requested_roles %></p>
And the requested_role partial should simply be:
<div class="fields">
<div>
<p>Requested role: <%= role_to_string(f.object.role) %></p>
<%= f.label :role, "Modify role" %>
<%= f.select :role, options_for_select([["Regista",1],["Sceneggiatore", 2],["Direttore della fotografia", 3], ["Operatore",4],
["Fonico", 5], ["Montatore", 6], ["Truccatrice",7], ["Costumista",8], ["VFX Artist",9],
["Produttore", 10], ["Attore",11], ["Attrice",12], ["Grip/Runner",13]], :selected => f.object.role) %>
<%= link_to_remove_fields "remove", f %>
</div>
</div>
Fixing your partial should fix your second problem with the links.
You might want to consider using Ryan's gem for nested_forms
https://github.com/ryanb/nested_form

Only show taxonomies that belong to the selected store model Ruby

When a store is selected I would only like to see the taxonomies that belong to the selected store. Does anyone have any idea how I might do this? Either with Ruby or Javascript
<h3>Stores Offered In</h3>
<ul class="multi-column-checkbox">
<% for store in Store.all %>
<li><%= check_box_tag "idea[store_ids][]", store.id,
#idea.stores.include?(store) %> <%= store.name %></li>
<% end %>
</ul>
<br />
<h3>Taxonomies Offered In</h3>
<% for store in Store.all %>
<% if store.has_taxonomies? %>
<ul class="multi-column-checkbox">
<h4><%= store.name %></h4>
<% for taxonomy in store.taxonomies %>
<li><%= check_box_tag "idea[taxonomy_ids][]",
taxonomy.id, #idea.taxonomies.include?(taxonomy) %> <%= taxonomy.name %></li>
<% end %>
</ul>
<% end %>
<% end %>
Ok -- lots going on here. First of all, I'm making the assumption that you're using rails 3 or rails 4
Also it looks like this is nested into the ideas model, which not taken into account here, you'll have to modify the code for that.
Firstly - Try not to make calls directly to a model in a view unless you absolutely have to, that should be done in your controller. Also, in your view make sure you have a binding element for taxonomies for the jquery call you'll make later.
your_main_view_referenced_in_your_question.html.erb
<h3>Stores Offered In</h3>
<ul class="multi-column-checkbox">
<%- #stores.each do |store| %>
<li>
<%= check_box_tag "store[ids]", store.id, false, :data => {:remote => true, :url => url_for( :action => 'get_taxonomies', :id => store.id ), :method => :put}, :class => 'input-large' %>
<%= store.name %>
</li>
<% end %>
</ul>
<br/>
<div id="taxonomies">
</div>
Next you need to create a controller action to respond to your ajax call.
stores_controller.rb
### Add an action to let you do an ajax call
def get_taxonomies
#store = Store.find params[:id]
end
Now you need to create a ujs file that is rendered from your controller action In my example I named the controller action get_taxonomies so by default the view rendered will be get_taxonimies.js.erb
get_taxonomies.js.erb
if ($(".store_" + <%= params[:id] %>).length) {
$(".store_" + <%= params[:id ] %>).remove();
} else {
$('#taxonomies').append("<%= escape_javascript(render(partial: '/stores/taxonomy', locals: {stores: #stores } )) %>");
}
if ($("[class^=store_]").length > 0) {
if ( $('#taxonomies').find('h3').length ) {
// do nothing - leave the h3 where it is
} else {
$('#taxonomies').prepend("<h3>Store Taxonomies</h3>");
}
} else {
$('#taxonomies').find("h3").remove();
}
Now while you could write all your html inline in the js file, it's kind of ugly and easier to edit it later if you put it in a partial - since the js.erb file is calling taxonomy, you'll need a partial with the same name
_taxonomy.html.erb
<div class="store_<%=#store.id%>">
<h4><%= #store.name %></h4>
<ul class="multi-column-checkbox">
<%- #store.taxonomies.each do |taxonomy| %>
<li>
<%= check_box_tag "[taxonomy_ids][]", taxonomy.id, false %>
<%= taxonomy.name %>
<% end %>
</li>
</ul>
</div>

Error display on ajax form in rails not working

I'm using an inline form for users to submit data to a table (note that I'm using CSS rather than html tables to achieve this). When an error is returned by the verification in the model, I want to highlight the input field using the Bootstrap error class and put the error message below the appropriate form field. I'm using AJAX to submit the form.
I'm having problems, this is what I have so far:
Controller:
def create
#travel = Travel.new(params[:travel])
#travel[:user_id] = current_user.id
convert_date # and return
if #travel.save
flash[:notice] = "Successfully saved trip"
#travels = Travel.where("user_id = ?",current_user)
respond_to { |format| format.js }
end
end
JS view:
<% if #travel.errors.any? %>
<% #travel.errors.full_messages.each { |msg| logger.debug(msg) } %>
<% #travel.errors.messages.each do |k,v| %>
<% logger.debug("#tf_#{k}") %>
$(<%= "#tf_#{k}" %>).insertAdjacentHTML("afterbegin","<span class="control-group error"><span class="controls">");
$(<%= "#tf_#{k}" %>).insertAdjacentHTML("beforeend","</span></span>");
$(<%= "#error_#{k}" %>).val("<%= "#{k} #{v}" %>");
<% end %>
<% else %>
$(":input:not(input[type=submit])").val("");
$("#travels_list").html("<%= escape_javascript( render(:partial => "travels") ) %>");
<% end %>
form partial:
<%= form_for #travel, :remote => true, :html => {:class => "form-inline", :id => "new-travel-form"} do |f| %>
<div class="row-fluid">
<span id="tf_city"><%= f.text_field :city, :placeholder => "London, UK", :class => "span3" %></span>
<span id="tf_arrive_date"><%= f.text_field :arrive_date, :class => "span2" %> </span>
<span id="tf_leave_date"><%= f.text_field :leave_date, :class => "span2" %> </span>
<span id="tf_notes"><%= f.text_field :notes, :placeholder => "e.g. staying at the Hilton", :class => "span3" %></span>
<%= f.submit "save", :class => "btn btn-primary span1" %>
</div>
<% end %>
<div class="row-fluid error" id="error_expl">
<span id="error_city" class="help-inline span3"></span>
<span id="error_arrive_date" class="help-inline span2"></span>
<span id="error_leave_date" class="help-inline span2"></span>
<span id="error_notes" class="help-inline span3">test</span>
</div>
The logger.debug in the JS is firing, so I know that the error is getting passed to the JS, but the insertAdjacentHMTL() doesn't seem to be working.
maybe this is not going to answer your question but i hope it could help to improve your code.
First, according to your code i guess you should have some associations like this in the model User:
has_many :travels
And in your model Travel:
belongs_to :user
So, in order to improve your code you can have this in your controller:
respond_to :js, only: [:create]
def new
#travel = current_user.travels.new
end
def create
#travel = current_user.travels.new(params[:travel])
if #travel.save
flash[:notice] = "Successfully saved trip"
#travels = current_user.travels
else
# I guess you should have some code here in case any validation fail. If you dont
# have validations for the model Travel, you don't need the if statement here.
end
end
About your problem, can you clarify what is "#tf_#{k}"?

How can I reset certain fields when my form is submitted?

I have my store form that's created by ajax and want to reset certain fields that it has. Here is my code, starting from where the form is rendered all the way to its own views:
Where its rendered:
pets/index.html.erb
<div class="tabbable">
<ul class="nav nav-tabs">
<li class="active">
Store
</li>
</ul>
<div class="tab-content">
<div class="tab-pane active add-store-form" id="tab1">
<%= render "stores/form" %>
</div>
</div>
</div>
How it's created:
Note: Both my new and create view have the same exact code.
new.js.erb & create.js.erb (just this 1 line)
$('.add-store-form').html('<%= escape_javascript(render(:partial => 'stores/form', locals: { store: #store })) %>');
Now on my Store form I want to reset the fields with a # by them:
<%= form_for(#store, :remote => true, :html => { :class => "add-form", :id => "sform" }) do |f| %>
# <%= f.text_field :name %>
# <%= f.check_box :personal %>
<%= f.collection_select :category_id, Category.all, :id, :name, {}, {} %>
# <%= f.text_field :address %>
<%= f.text_field :website %>
# <%= f.text_field :phone_number %>
<%= f.submit "Create" %>
How do I reset these certain fields only?
This is kind of a duplicate question of Clear form fields with jQuery .
So, you should include a js file (not new.js.erb or create.js.erb) that has a function like this:
$('#sform').live('submit', function() {
$('#name').val(""); # this only resets the name field, provided it has the id 'name'
});
You have other examples in the answers to that question I linked to. Just notice that they use the click on a button to reset the fields while I suggested using your form submit event when you click your Create button.

In my comment app when i refresh the page comments disappears

My comment app works ,but the only problem is whenever i refresh the page the comments disappear.In the log it shows the body is inserted in the comments table(it is saved).What am i doing wrong here?Any help will be appreciated.Thank you in advance.
View#show
<div id="comments"></div>
<%= form_for :comment,:remote => true,:url=> {:controller=>"comments",:action=>"create"},:html => { :id => 'new-comment'} do |f| %>
<%= f.text_area(:body) %>
<div class="errors"></div>
<%= f.submit "post" %>
<% end %>
Comment controller
class CommentsController < ApplicationController
respond_to :js
def create
#deal=Deal.find(1)
#comment =#deal.comments.build(params[:comment])
#comment.save
respond_with( #comment, :layout => !request.xhr? )
end
def show
#comment=Comment.all
#deal=Deal.find(1)
#comment=#deal.comments
end
end
create.js.erb
$('#comments').append("escape_javascript(#comment.body)");
I don't see where your comments are being display in your show template.
How about something like this?
<div id="comments">
<% #comments do |comment| %>
<%= comment.body %>
<% end %>
</div>
<%= form_for :comment,:remote => true,:url=> {:controller=>"comments",:action=>"create"},:html => { :id => 'new-comment'} do |f| %>
<%= f.text_area(:body) %>
<div class="errors"></div>
<%= f.submit "post" %>
<% end %>
Note, you need to set #comments in the controller or use another method of getting comments, e.g. #view = View.find(params[:id]) and <%= #view.comments.each do |comment| %>...
I guess the comment has a belongs_to relationship with the post that is not assigned.
In your form you should add
<%= f.hidden_field :post_id, #post.id %>
If you want to play by the book, post_id should be attr_protected and instead assign it manually in the comments controller
#comment = Comment.new(params[:comment])
#comment.post_id = params[:comment][:post_id]
#comment.save

Categories

Resources