bit new to Ajax and rails.
I have a link on an image that when clicked should replace the image.
Here's my link in the view:
<div id="flag_<%= message.id %>">
<%= link_to image_tag("white_star.png"), flag_message_path(message), remote: true %>
</div>
this calls flag method on messages controller. For format.js i have flag.js:
{$('#flag_<%=#message.id%>').html('<% if #message.flag == false %><img alt="White_star" src="/assets/white_star.png" title="flag">
<% else %>
<img alt="Red_star" src="/assets/red_star.png" title="flag">
<% end %>');
}
this returns to the browser:
{
$('#flag_94').html('<img alt="White_star" src="/assets/white_star.png" title="flag">
');
}
which seems ok to me, yet nothing happens.... Any thoughts??
thanks
Everything seems ok, but I would drop the surrounding accolades in your format.js.erb. Those are not needed.
If there is an error in your javascript, you should see it in the javascript console.
It is generally good practice to extract code like this into a partial.
So you would have a replace_image.html.erb :
<% if #message.flag == false %>
<img alt="White_star" src="/assets/white_star.png" title="flag">
<% else %>
<img alt="Red_star" src="/assets/red_star.png" title="flag">
<% end %>
and in your format.js.erb you would just do
$('#flag_<%=#message.id%>').html("<%= escape_javascript(render :partial => 'replace_image') %>");
Hope this helps.
Related
I've been trying to wrap my head around this for days now, but I can't seem to find a solution for this problem.
Basically what I want to do is a feed similar to Facebook. A feed with multiple posts, of which each has comments/replies.
Now what I can't get to work is an AJAX "Load more" button for each post. I've only got it working for all posts at once, but not for individual ones.
What I have so far:
The feed:
<% #posts.each do |post| %>
<%= render "posts/thread", post: post %>
<% end %>
The threads:
<%= render post %>
<% replies = post.replies.paginate(:page => params["replies#{post.id.to_s}"], :per_page => 2) %>
<%= render replies %>
<%= will_paginate replies, :param_name => 'replies'+post.id.to_s %>
<%= link_to "Load More", "#", class: "load-more", id: post.id, :remote => true %>
The posts:
<div class="post" data-id="<%= post.id %>">
## content ##
</div>
pagination.coffee:
jQuery ->
$('.load-more').on 'click', ->
postId = $(this).attr('id')
more_posts_url = $('#post-'+postId+' .pagination .next_page').attr('href')
if more_posts_url
$('.load-more').html('<img src="/assets/ajax-loader.gif" alt="Loading..." title="Loading..." />')
$.getScript more_posts_url
return
return
index.js.erb:
<%= #posts.each do |post| %>
$('#post-<%= post.id %>').append('<%= j render post.replies %>');
<% end %>
But this does nothing.
I really don't understand how JS works for multiple records on one page.
I suppose this could help: https://jsfiddle.net/se708oou/2/
Main points of difference:
You should loop through all of the .load-more elements
$('.load-more').each(function() {
Change reference to use this
$(this).on('click', function() {
(Miscellaneous) This is how you take data-* in jQuery:
postId = $(this).data('id');
Cheers! :)
Your posts div
<div class="post" data-id="<%= post.id %>">
...
</div>
Has a class of post and a data attribute id, but in index.js.erb you are trying to select #post-<%= post.id %>
That selector isn't in the dom, You need to change your selector to
$('.post[data-id=<%= post.id %>').append('<%= j render post.replies %>');
I've been able to implement a search function using AJAX in Rails but when a user types in a search query and doesn't find anything the result currently displays nothing. Instead of this, I want to display a message such as: 'Sorry nothing was found!', but I can't seem to get this to work.
This is my code from the index.js.erb file:
$('#products').append('<%= escape_javascript render(#products) %>');
$('.pagination').replaceWith('<%= escape_javascript paginate(#products) %>');
This is the code in my index.html.erb file:
<%= form_tag products_path, method: :get, authentication: false, id: 'search-form' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search" %>
<% end %>
<div class="small-block-grid-2 medium-block-grid-3 large-block-grid-3" id="products">
<% #products.each do |product| %>
<%= render product %>
<% end %>
</div>
And finally this is the bit of relevant code in my products_controller.rb file:
respond_to :html, :js, :json
def index
#products = if params[:search].present?
Product.where("name LIKE ?", "%#{params[:search]}%")
else
Product.all
end
#products = Product.order(created_at: :desc).page(params[:page]).per(13)
respond_with #products
end
def search
#products = Product.where("name LIKE ?", "%#{params[:search]}%")
render #products
end
Sorry I should've included this in the question as well. Now I am able to get this message of "Sorry nothing was found!" message to display when a search query comes up with nothing, BUT the problem is that I have to press enter twice in order for it to display the message. What can I do to change my code here so when nothing is found the first time it displays: "Sorry nothing was found!"?
This is the code in my assets/javascripts/products.js file:
$(document).ready(function(){
$('#search-form').submit(function(event){
event.preventDefault();
var searchValue = $('#search').val();
$.get('/products/search?search='+searchValue)
.done(function(data){
console.log(data);
if ($("#products").children().length != 0){
$('#products').html(data);
}else{
$('#products').html("<h3>Sorry nothing was found!</h3>");
}
});
});
});
I believe that's all the necessary information needed to understand this question. If you need more clarification in order to understand what I'm doing, I'll be glad to provide it.
Thank you all for your input!
I faced the same problem with this guy
I change rjs to js.erb just like him. And we all use <%= button_to 'Add to Cart',line_items_path(:product_id => product) ,:remote=>true %> to send an AJAX request to the controller. format.js to fine and execute create.js.erb. But the cart did not add anything.
log result :
Rendered line_items/_line_item.html.erb (4.3ms)
Rendered carts/_cart.html.erb (8.0ms)
Rendered line_items/create.js.erb (8.8ms)
That's the index.html.erb we send the AJAX request
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<h1>Your Pragmatic Catalog</h1>
<% #products.each do |product| %>
<div class="entry">
<%= link_to image_tag(product.image_url), line_items_path(:product_id => product), html_options = {:method => :post} %>
<h3><%= product.title %></h3>
<%=sanitize product.description %>
<div class="price_line">
<span class="price"><%= number_to_currency(product.price,:precision=>3) %></span>
<%= button_to 'Add to Cart',line_items_path(:product_id => product) ,:remote=>true %>
</div>
</div>
<% end %>
That's the line_items controller function to handle the request
# POST /line_items
# POST /line_items.json
def create
# for exercise only
session[:counter] = nil
#cart = current_cart
product = Product.find(params[:product_id])
#line_item = #cart.add_product(product.id)
respond_to do |format|
if #line_item.save
format.html { redirect_to store_index_path }
format.js
format.json { render json: #line_item, status: :created, location: #line_item }
else
format.html { render action: "new" }
format.json { render json: #line_item.errors, status: :unprocessable_entity }
end
end
end
create.js.erb
$('#cart').html("<%= escape_javascript(render(#cart)) %>");
I fixed the problem.
Thanks to the great article which tell me the ability of firebug to see the source of response from AJAX request.
And JSLint helps me checkout the javascript syntax.
And finally I would like to thanks the Firebug which is such a great tool.
The problem is that the javascript is not being executed if there is any syntax error.
In my problem:
I should use single-quoted instead of double-qouted to wrap the render results. The render results comes out with many HTML with "", and "" which wrap them will cause syntax error in javascript. (double-qouted in double-qouated is not allowed)
So I simply change $('#cart').html("<%= escape_javascript(render(#cart)) %>"); to
$('#cart').html('<%= escape_javascript(render(#cart))%>');
I hope this answer will help the others who also suffer from this nightmare staff.
Help me increase the question rate if this is possible :)
Let's use j() helper method: $('#cart').html("<%=j render(#cart) %>");
I was trying out Rails again, this time the 3 version, but I got stuck while writing tests for an action that I only call remotely.
A concrete example:
Controller
class PeopleController < ApplicationController
def index
#person = Person.new
end
def create
#person = Person.new(params[:person])
#person.save
end
end
View (index.html.erb)
<div id="subscription">
<%= form_for(#person, :url => { :action => "create" }, :remote => true) do |f| %>
<%= f.text_field :email %>
<%= f.submit "Subscribe" %>
<% end %>
</div>
View (create.js.erb)
<% if #person.errors.full_messages.empty? %>
$("#subscription").prepend('<p class="notice confirmation">Thanks for your subscription =)</p>');
<% else %>
$("#subscription").prepend('<p class="notice error"><%= #person.errors.full_messages.last %></p>');
<% end %>
How can I test that remote form submission? I would just like to find out if the notice messages are being presented correctly. But if I try to do just
test "create adds a new person" do
assert_difference 'Person.count' do
post :create, :people => {:email => 'test#test.com'}
end
assert_response :success
end
It will say that the "create" action is missing a template.
How do you guys usually test remote calls?
Could you just use the 'xhr' function instead of the 'post' function? An example can be found at http://weblogs.java.net/blog/2008/01/04/testing-rails-applications, if you search for 'xhr'. But even then, I'm curious, even with a remote call, don't you need to return SOMETHING? Even just an OK header?
I have a Note model, which can contain have either an image link attachment (linktype = "image" or some text (linktype = "text). When I display the notes, the method of display changes depending on the linktype. An example is:
<% #notes.each do |q| %>
<h2 class="title"><%= q.name %></h2>
<% if q.linktype == "other"%>
<script type="text/javascript">some javascript</script>
<% elsif q.linktype == "text"%>
<%= q.text %>
<% elsif q.linktype == "image"%>
<img src="<%= q.link %>" />
<% end %>
<% end %>
I have to display the notes in a few different views in my site, so rather than have to repeat the viewing code multiple times, I want to have it in one place and refer to it from different views.
My initial thought was to put the display code in a helper, something like this:
<% #notes.each do |q| %>
note_display(q.linktype, q.link)
<% end %>
But some of the displaying involves javascript (line 4 in first code block). Can I still use a helper method, even though I would need it to return javascript? If so, how do I do it? Thanks for reading.
There's nothing special about javascript, you can return it from helpers as you would return other html content. The only thing I would suggest is to use helpers for tags like
image_tag(q.link)
javascript_tag("some javascript")
content_tag("h2", q.name, :class => "title")
As far as ERB is concerned, JavaScript is just string content like anything else rendered by a template. So your helper method can just construct and return a string:
def note_display(note)
content = ''
content << content_tag('h2', h(note.name), :class => 'title')
if note.linktype == 'other'
content << javascript_tag("some javascript")
elsif note.linktype == 'text'
content << h(note.text)
elsif note.linktype == 'image'
content << image_tag(note.link)
end
content
end
You can use this helper method using:
<% #notes.each do |n| %>
<%= note_display(n) %>
<% end %>