Rails AJAX Destroy - Re-render index issues - javascript

I have an issue with a Rails AJAX app which is confusing me, even though it seems very simple! I am dealing with class Order in a simple point of sale rails app. The request is being made as the order will be deleted on page refresh (but I am getting no refresh of #orders) as I thought I am specifying in destroy.js.erb.
orders/index.html
<div id="orders">
<%= render 'orders/index' %>
</div>
<%= link_to 'New Order', new_order_path, remote: true %>
<div id="order-form" style="display:none;"></div>
orders/_index.html
<% if #orders.any? %>
<% #orders.each do |order| %>
<%= link_to "Show #{order.id}", order_path(order), class: "something" %>
<%= link_to "Delete #{order.id}", order_path(order), method: :delete, class: "something" %>
<%= link_to "Delete order with ajax", order_path(order), remote: true, method: :delete %>
<% end %>
<% else %>
<p>No orders yet</p>
<% end %>
destroy.js.erb
//When deleting order on order index - render orders again.
$('#orders').html("<%= j (render 'orders/index') %>");
and the relevant actions from orders_controller.rb
class OrdersController < ApplicationController
respond_to :html, :js
def index
#orders = Order.paginate(page: params[:page])
if params[:search]
#orders = Order.search(params[:search]).order("created_at DESC")
else
#orders = Order.all.order('created_at DESC')
end
end
def destroy
#order = Order.find(params[:id])
if #order.destroy
flash[:notices] = ["Order was successfully deleted"]
redirect_to orders_path
else
flash[:notices] = ["Order could not be deleted"]
render order_path(#order)
end
end
I suspect the issue is in my orders_controller destroy or index action, but I am a little unclear on a number of the ways of working with AJAX in Rails.
Link to repo - https://github.com/benhawker/point-of-sale-rails

Might be because after your destroy you're redirecting to the index path

I am getting no refresh of #orders
Your JS is likely not firing, you'll need the following:
def destroy
#order = Order.find params[:id]
respond_to do |format|
if #order.destroy
format.js
format.html { redirect_to orders_path, notice: "Order was successfully deleted" }
else
format.js
format.html { render order_path(#order), notice: "Order could not be deleted" }
end
end
end
This will fire app/views/orders/destroy.js.erb, which seems okay in your OP.

Try Updating your destroy action to
#order = Order.find(params[:id])
#order.destroy
#orders=Order.all
remove all the redirects
will work.

Related

Display a notice in rails after an ajax call

Hi I have a status controller where I render js template when a user deletes a status. This is the controller code:
def destroy
#status = Status.where(id: params[:id]).first
if #status.present?
make_subject(#status, Constants::Subject::BREAK)
respond_to do |format|
format.html { redirect_to root_path, notice: 'deleted' }
format.json { head :no_content }
format.js { render layout: false }
end
end
end
In my destroy.js.erb, I have:
$("#clear_status_<%= #status.id %>").fadeOut();
I have a partial which renders flash messages
<div id = "notice_wrapper">
<% if alert %>
<div class = "alerty">
<p> <%= alert %> </p>
</div>
<% elsif notice %>
<div class = "notice">
<p> <%= notice %> </p>
</div>
<% end %>
</div>
Once the status gets deleted successfully I want a notice which informs the user that the status is deleted successfully I want to display that message by rendering this partial.
How can I achieve this?
You can do it with JQuery. If put your own element instead of 'nav' where u want to show notice.
$('nav').after("<div class='alert alert-success'> Successfully Destroyed </div>");
$("#clear_status_<%= #status.id %>").fadeOut.fadeOut(250, function(){
$(this).remove();
});
Also Update your destroy method.
def destroy
#status = Status.find_by(id: params[:id])
if #status.present?
make_subject(#status, Constants::Subject::BREAK)
respond_to do |format|
#format.html { redirect_to root_path, notice: 'deleted' } # yr calling it async to destroy. format.html is needless.
format.json { head :no_content }
format.js
end
end
end
You will need a way to tell in your response if the delete was successful. And if it was, then show your notice.
For this purpose, I'll create a #deleted variable which will be boolean, and will be set to true if delete is successful, otherwise, false.
Following is the controller code:
def destroy
#status = Status.find(params[:id])
#deleted = false
if #status.destroy
#deleted = true
end
respond_to do |format|
format.html
format.json
format.js
end
end
and the destroy.js.erb file, you will have something of this sort:
<% if #deleted %>
$(".notice").html(<%= render 'notice_partial' %>)
<%= escape_javascript(alert("deleted successfully")) %>
<% end %>
$("#clear_status_<%= #status.id %>").fadeOut();

Including Ajax/JS to my voting system in Rails

How do i make it so that it does not refresh the page? instead it will just update the count numbers? Any help would be appreciated!
Stories controller:
def like
like = Like.create(like: params[:like], user: current_user, story: #story)
if like.valid?
flash[:success] = "Your selection was succesful"
redirect_to :back
else
flash[:danger] = "You can only like/dislike a story once"
redirect_to :back
end
end
index.html.erb:
<div class="pull-right">
<%= link_to like_story_path(story, like: true), :method => :put, :remote => true do %>
<i class="glyphicon glyphicon-thumbs-up"></i><%= story.thumbs_up_total %>
<% end %>
<%= link_to like_story_path(story, like: false), :method => :put, :remote => true do %>
<i class="glyphicon glyphicon-thumbs-down"></i><%= story.thumbs_down_total %>
<% end %>
</div>
Story.rb model:
def thumbs_up_total
self.likes.where(like: true).size
end
def thumbs_down_total
self.likes.where(like: false).size
end
The controller should respond_to the js "format", as described in Working with JavaScript in Rails.
Instead of redirect_to :back, respond with a meaningful status code, for example 201 for success (when a new resource has been created) or 400 for a bad request.
See RFC 2616, section 10 - Status Code Definitions.
Then, in your JS, handle the ajax:success event. This is also described in Working with JavaScript in Rails.
Let me show you an example:
First change your StoriesController as follow:
def like
#like = Like.create(like: params[:like], user: current_user, story: #story)
if #like.valid?
respond_to do|format|
format.js
end
else
respond_to do|format|
format.js {render status: 403, js: "alert('You can only like/dislike a story once'"}
end
end
end
And create a file called like.js.erb within your stories view directory with following content.
<% if #like.like %>
var $element = $(".glyphicon.glyphicon-thumbs-up");
<% else %>
var $element = $(".glyphicon.glyphicon-thumbs-down");
<% end %>
var oldCount = parseIn($element.text());
$element.text(oldCount + 1);
With the examples aside, you should at least Rails Guide in order to be able to use ajax effectively in rails. It's not that difficult.

jQuery .load()-function doesn't reload element (Rails)

In my Rails Project, I am trying to alter an instance variable via JS in a controller response (create.js.erb) and then reload an HTML-Element that makes use of the instance variable. But it doesn't work. Is it possible? This is just an example.
I also want to display the newly created object. But as I don't seem to understand the mechanism of exchanging information between rails and JS, I wanted to keep it simple here.
vocabs-controller.rb
def new
#user = current_user
#vocab = #user.vocabs.build
#vocabs = #user.vocabs.all
#count = #vocabs.count
.
.
end
def create
#user = current_user
#vocab = #user.vocabs.build(vocab_params)
#count = #user.vocabs.count
.
.
respond_to do |format|
format.html do
redirect_to new_user_vocab_path(#user)
flash[:success] = "Vocab created!"
end
format.js {render :layout=>false}
end
else
respond_to do |format|
format.html {render 'vocabs/new'}
format.js
end
end
new.html.erb (from here I make the call to the controllers create action)
<div class="panel-body">
<%= form_for(#vocab,
url: user_vocabs_path(#user),
method: :post, remote: true) do |f| %>
.
.
.
<%= f.submit "Add", class: "btn btn-large btn-primary" %>
<% end %>
<h4>
<%= #count %> Vocabs in your collection
</h4>
<%= link_to "(Show)", "#", id: "show_link" %>
<%= link_to "(Hide)", "#", id: "hide_link" %>
<ul class='vocabs <%= #vocabs_class %>'>
<% #vocabs.each do |vocab| %>
<%= render vocab %>
<% end %>
</ul>
<hr>
<%= link_to "Back", home_user_path(#user) %>
</div>
.
.
create.js.erb
<% #count+=1 %>
$('h4').load();
The server recognizes that I made a JS request and also renders create.js.erb with 200 OK. But the .load() function doesn't seem to reload the h4-Element with the new data.
When I was trying to .load() the div-element that contains the formular fields, these also weren't updated. The text input was still visible.
Further question: Where can I debug the code in JS Controller responses? I can't find them neither in Chrome's dev tools nor in Rails's server output.
If I follow you correctly, try
Add an id attribute to h4:
<h4 id="count-header">...</h4>
And in the .erb.js callback:
$('#count-header').text('<%= #count += 1 %> Vocabs in your collection');

Form_for doesn't work with JS/JQuery

I have problems getting a form to work when I use JavaScript with it.
Without the remote option set to true all works fine but as soon as I
set it, change the controller and create the needed JS files it produces an
POST .. 500 Internal Server Error
when clicking on the submit button.
Furthermore the reply-preview shows me a Rails Error Page saying
NoMethodError in Vocabs#create and undefined method > for nil:NilClass
in a related partial (which works fine before using JS)
The form (vocabs/_new_form.html.erb) looks like this:
<%= form_for #vocab, remote: true do |f| %>
<%= render 'fields', f: f %>
<%= f.submit "Add", class: "btn btn-large btn-primary" %>
<% end %>
The vocab_controller's create action like this:
def create
#user = current_user
#vocab = current_user.vocabs.build(vocab_params)
#vocabs = #user.vocabs.paginate(page: params[:page])
respond_to do |format|
format.html {
if #vocab.save
flash.now[:success] = "Vocab created!"
redirect_to root_url
else
flash.now[:error] = "Vocab not saved!"
render 'new'
end
}
format.js
end
end
The create.js.erb like this:
$('#new_vocab').remove();
Of course I want to do more than just to remove the form but as I didn't even manage to do that I wanted to keep it simple.
_fields.html.erb:
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.label :nl_word, #user.native_language %>
<%= f.text_field :nl_word %>
<%= f.label :fl_word, #user.foreign_language %>
<%= f.text_field :fl_word %>
<%= f.label :tag, "Your Tag" %>
<%= f.text_field :tag%>
<%= f.label :importance, "Importance" %>
<%= f.select(:importance, options_for_select(
StaticData::IMPORTANCE_SEED, :selected => f.object.importance)) %>
</div>
I hope I could explain myself good enough to get some help here. I tried for hours to find the solution to the problem myself and was looking for similar questions here without finding any and without getting anywhere.
With the help of a friend I found out that the main problem was that I didn't provide any validation for the vocab object i wanted to create in the form (_new_form.html.erb), when processing it with JS.
So I changed the vocab_controller.rb to
def create
#user = current_user
#vocab = current_user.vocabs.build(vocab_params)
#vocabs = #user.vocabs.paginate(page: params[:page])
respond_to do |format|
if #vocab.save
flash.now[:success] = "Vocab created!"
format.html do
redirect_to root_url
end
format.js
else
flash.now[:error] = "Vocab not saved!"
format.html do
render 'new'
end
format.js
end
end
end
That does the trick, and my form works with JS now.

The AJAX request cannot see the effect without refresh the browser in Rails

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

Categories