I'm trying to do an Ajax call on Ruby on Rails. When I select 2 collection_select's the third has to be rendered by Ajax. I'm new to Ruby on Rails, so if anybody could help me, I'd be thankful.
_form.html.erb:
<%= form_for(#preco_servico) do |f| %>
<div class="field">
<%= f.label :produto %>
<%= collection_select(:preco_servico, :produto, Produto.order('tipo'), :tipo, :tipo) %>
</div>
<div class="field" >
<%= f.label "Análise" %>
<%= collection_select(:preco_servico, :analise, TipoAnalise.order('tipo'), :tipo, :tipo) %>
</div>
<div class="field" id="parametro-select", :remote >
</div>
...
<% end %>
application.js:
jQuery(function($) {
$("#preco_servico_analise").change(function() {
var produto_id = $('select#preco_servico_produto :selected').val();
var analise_id = $('select#preco_servico_analise :selected').val();
$.get('/preco_servicos/update_parametro/' + produto_id + '/' + analise_id, function(data){
$("#parametro-select").html(data);
})
return false;
});
})
The method on controller:
def update_parametro
#precos = PrecoServico.where(:analise => params[:analise], :produto => params[:produto])
#sub_parametros = []
#precos.each do |preco|
#sub_parametros = Parametro.where("nome NOT IN (?)", preco.parametro)
end
respond_to do |format|
format.js
end
end
I've already included the code below on application.html.erb:
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
And the file update_parametro.js.erb:
sub_parametro <%= collection_select(:preco_servico, :parametro, #sub_parametros, :nome, :nome) %>
On console I get this:
Started GET "/preco_servicos/update_parametro/produto2/analise2"
for 127.0.0.1 at 2014-01-28 23:25:21 -0200 Processing by
PrecoServicosController#update_parametro as / Parameters:
{"preco_servicos"=>"preco_servicos",
"update_parametro"=>"update_parametro", "produto"=>"produto2",
"analise"=>"análise2"} PrecoServico Load (0.2ms)
SELECT preco_servicos.* FROM preco_servicos WHERE
preco_servicos.analise = 'análise2' AND preco_servicos.produto
= 'produto2' Rendered preco_servicos/update_parametro.js.erb (0.5ms) Completed 200 OK in 8ms (Views: 6.0ms | ActiveRecord: 0.2ms)
It tells me it is rendered, but nothing changes on screen and nothing appears in firebug.
Related
I'm fairly new to programming with ruby . I'm trying to create a Livesearch with AJAX, but is giving me headaches. The basic idea is that when a user creates a node, can be stored in the same: information of the user who created it , the parent node , etc. For this I did a live search where the user enters the ID of the parent node and the user data that corresponds to that node automatically appear . Then, in the same view, I want to create the node. So far I have the following code, which I'm not doing work.
I want something like this:
(source: subeimagenes.com)
Problems:
AJAX not working , I'm sure I 'm forgetting something important
Do not know how to pass the value " parent_id " (u.id in _users.html.erb, result of " live search ") to create the node.
nodes_controller.rb
def new
#node = Node.new
end
def search
#node = Node.new
#parent = Node.search(params[:search]).where(:ocuped => true)
if not #users.nil?
if #users.count == 1
#node_incomplete = #users.nodes.where(" sons < ? AND ocuped = ?",2,true).first
else
#node_incomplete = #users.first.nodes.where(" sons < ? AND ocuped = ?",2,true).first
end
#son_of_incompleted_node = #node_incomplete.children
end
respond_to do |format|
format.html
format.js
end
end
search.html.erb
<%= form_for #node, :id => "users_search" do |f| %>
<%= f.text_field :search, :value => params[:search], :autocomplete => 'off' %>
<div id='users'>
<%= render 'users' %>
</div>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :ocuped, :value => true %>
<%= f.text_field :custom_node_name %>
<%= f.check_box :terms_of_service,{}, true,false %>
<%= f.submit "Create", class: "button postfix" %>
<% end %>
_users.html.erb
<% if not #parent.nil? %>
<% #parent.each do |u| %>
<ul class="inline-list">
<li class="img-simple" style = "text-align: center; background-image: url('<%= u.user.profile_img %>')"></li>
<li style="display:table-cell; vertical-align: middle;"><h6><%= u.user.name %></h6><p><%= u.user.email %></p></li>
</ul>
<% end %>
node.rb
def self.search(search)
self.where('id = ? ', search.to_i)
end
application.js
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require foundation
//= require_tree .
$(function() {
$("#users_search input").keyup(function() {
$.get($("#users_search").attr("action"), $("#users_search").serialize(), null, "script");
return false;
});
});
nodes.js.cofee
jQuery ->
# Ajax search on keyup
$('#users_search input').keyup( ->
$.get($("#users_search").attr("action"), $("#users_search").serialize(), null, 'script')
false
)
views/nodes/search.js.erb
$('#users').html('<%= escape_javascript(render("users")) %>');
I have a rails 4 app where I'm following basically this railscast:
_form.html.erb:
<%= form_for #store, do |f| %>
<%= f.fields_for :products do |builder| %>
<%= render "product_fields", f: builder %>
<% end %>
<%= link_to_add_fields "Add Product", f, :products %>
<% end %>
_product_fields.html.erb
<%= f.select :the_product_type, %w[Shelves, Tools, Wires]%>
<div>
<%= f.fields_for :product_fields do |builder| %>
<%= builder.text_area :name_of_product_field %>
<% end %>
</div>
My JS looks like:
$('form').on('click', '.add_fields', function(e) {
var regexp, time;
time = new Date().getTime();
regexp = new RegExp($(this).data('id'), 'g');
$(this).before($(this).data('fields').replace(regexp, time));
return e.preventDefault();
});
My issue is that when I click the Add Product button, I can only see a select. I can't see the name_of_product_field textarea. But I can't figure out why I can see the select if I can't see the textarea?
product_fields is a nested attribute which you have not build anywhere in your code which is why you are not seeing it.
Assuming that a product has_many product_fields, you can resolve this issue in two ways, choose one that suits you:
1. Build it at Controller level
Build the product_fields in the Controller#action which is rendering the problematic view:
def action_name
#store = Store.new
product = #store.products.build
product.product_fields.build
end
2.Build it at View level
Update the fields_for in _product_fields.html.erb as below:
<%= f.fields_for :product_fields, f.object.product_fields.build do |builder| %>
I have the following action on my controller for a Comment:
def create
#comment = comment.new(params[:comment])
#comment.replyable_type = params[:replyable_type]
#comment.replyable_id = params[:replyable_id]
#comment.user = current_user
respond_to do |format|
format.html do
# Removed
end
format.js do
#comment.save
end
end
end
and the following create.js.erb file for when it gets called by a remote form:
console.log('It did run');
<% if #comment.errors.any? %>
<% #comment.errors.full_messages.each do |msg| %>
console.log('<%= javascript_escape(msg) %>');
<% end %>
<% else %>
comment = "<%= escape_javascript render #comment %>";
<% if #comment.replyable_type == 'Comment' %>
$('#comment-<%= #comment.id %> > .replies').prepend(comment));
<% else %>
$('.comments').prepend(comment);
<% end %>
// removed
<% end %>
Along with the following form partial:
<%= form_for(Comment.new, url: comments_path, remote: true) do |f| %>
<div class="comment-form" id="comment-<%= replyable_type %>-<%= replyable_id %>">
<%= f.text_area :content, cols: 60, rows: 5 %>
<%= hidden_field_tag :replyable_id, replyable_id %>
<%= hidden_field_tag :replyable_type, replyable_type %>
<%= f.submit 'Send Comment', class: 'btn btn-primary' %>
</div>
<% end %>
replyable is a polymorphic association, which can be either a Post or a Comment object. When I submit a copy of the form on a page for a post, where replyable_type is Post and replyable_id is a post's ID, it works fine. When I submit a copy of the form on the same page, with the replyable_type set to Comment, and the replyable_id set to a comment's ID, the view the javascript does not run, at all. The action on the controller runs, using Firebug I can see the rendered javascript being sent back in response to the post request, and the comment is added to the database.
There are no errors in either the Rails console for generating the javascript or in the Firebug console to do with running the generated javascript. There are also no errors in the #comment.errors array. Even the first console.log in the Javascript is not run when the replyable object is a comment, despite being present in the rendered javascript.
What could cause this? I am using Rails 3.2.13 on Ruby 1.9.3
On the user's page there are microposts and each of them have it's own comment form and comments. Using "Endless Page" railscast i'm trying to create "show more comments" button, which will load comments by AJAX. But it's not working.
The problem is in show.js.erb file because:
1) common pagination of comments (without AJAX) is working well
2) "show more button" is working well too. I tested it on the users list page
I think "show more comments" not working because it don'understand <%= j render(comments) %> , <%= j will_paginate(comments) %> and i should have here variables like <%= j render(#comments) %> , <%= j will_paginate(#comments) %>.
But when i try to write in my users_controller.rb
def show
#micropost = Micropost.find(params[:micropost_id])
#comments = #micropost.comments
end
it's not working because on my user's page there are many microposts and i have an error "Couldn't find micropost without an id". So in my microposts/_micropost.html.erb i had to use this
<% comments = micropost.comments.paginate(:per_page => 5, :page => params[:page]) %>
<%= render comments %>
Can anyone please help? How should i change my show.js.erb?
users/show.html.erb
<%= render #microposts %>
microposts/_micropost.html.erb
...
micropost's content
...
<%= render 'comments/form', micropost: micropost %>
<% comments = micropost.comments.paginate(:per_page => 5, :page => params[:page]) %>
<div class="commentaries">
<%= render comments %>
</div>
<div id="append_and_paginate">
<%= will_paginate comments, :class =>"pagination", :page_links => false %>
</div>
javascripts/users.js.coffee
jQuery ->
if $('.pagination').length
$('#append_and_paginate').prepend('<a id="append_more_results" href="javascript:void(0);">Show more</a>');
$('#append_more_results').click ->
url = $('.pagination .next_page').attr('href')
if url
$('.pagination').text('Fetching more...')
$.getScript(url)
users/show.js.erb
$('.commentaries').append('<%= j render(comments) %>');
<% if comments.next_page %>
$('.pagination').replaceWith('<%= j will_paginate(comments) %>');
<% else %>
$('.pagination').remove();
<% end %>
<% sleep 0.3 %>
Bennington, in users/show.html.erb you have
But #microposts is not defined in your controller. What I think you want is to define #microposts as all the microposts associated with what, a User?
If so, you'd want something like `#microposts = Micropost.where(:user_id => current_user.id) or something.
I am using the setup of the R.B. railcast - #197 Nested Model Form Part 2 to dynamically add fields to the form but i am having issues getting the Tokeninput fields to work.
Form:
<%= form_for(current_user, :url => user_products_path) do |f| %>
<%= f.error_messages %>
<%= f.fields_for :user_products do |builder| %>
<%= render "user_product_fields", :f => builder %>
<% end %>
<%= link_to_add_fields "Add a UserProduct", f, :user_products %>
<%= f.submit "Create" %>
<% end %>
This is my user_product_fields partial, the token text_fields are what I'm having the issue with:
<div class="fields">
<%= f.label :product_token, "Product" %>
<%= f.text_field :product_token, :id => 'product_token' %>
<%= f.label :address_token, "Address" %>
<%= f.text_field :address_token, :id => 'address_token' %>
<%= f.label :price %>
<%= f.text_field :price %>
<%= link_to_remove_fields "remove", f %>
</div>
Jquery Tokeninput functions inside of my application.js:
$(function() {
$("#product_token").tokenInput("/products.json", {
prePopulate: $("#product_token").data("pre"),
tokenLimit: 1
});
});
$(function() {
$("#address_token").tokenInput("/business_addresses.json", {
prePopulate: $("#address_token").data("pre"),
tokenLimit: 1
});
});
What the nested form does in the function is this:
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));
}
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
This line here:
var new_id = new Date().getTime();
Makes the tokeninput fields dynamic, this is what i pulled up from the HTML, notice the changing long numbers in the fields. This is because of the line above.
<label for="user_user_products_attributes_1313593151076_product_token">Product</label>
<label for="user_user_products_attributes_1313593146876_product_token">Product</label>
<label for="user_user_products_attributes_1313593146180_product_token">Product</label>
How can i get my token fields to work when the fields keep changing up?
Thank you.
EDIT: New working code.
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g")
$(content.replace(regexp, new_id)).insertBefore($(link).parent()).trigger("nestedForm:added");
}
$('div.fields').live("nestedForm:added", function() {
$("#product_token", $(this)).tokenInput("/products.json", {
prePopulate: $("#product_token", $(this)).data("pre"),
tokenLimit: 1
});
});
When trying to data-pre with TokenInput:
def new
#user_product = current_user.user_products.build
# This line below is for TokenInput to work, This allowed me to use #products.map on the form.
#products = []
end
def edit
#user_product = UserProduct.find(params[:id])
# This line below had to find the Product associated with the UserProduct
#products = [#user_product.product]
end
You can user jQuery's insertBefore instead of before as that will return the inserted element. It will help you to trigger some event. You can have a listener on this event, in which you can have you token-input code. You should also use class instead of id, as many elements can have same class, but no two elements should have same id.
$(content.replace(regexp, new_id)).insertBefore($(link).parent()).trigger("nestedForm:added");
$('div.fields').live("nestedForm:added", function() {
$(".product_token", $(this)).tokenInput("/products.json", {
prePopulate: $(".product_token", $(this)).data("pre"),
tokenLimit: 1
});
});
This is just an idea, code is not tested.