Ajax success event in Rails 3 - ruby-on-rails

Rails newbe here. I've got links that do ajax query to server:
<%= link_to g.name, g, :class => 'link link-to-gallery', :remote => true %>
JS view that loads data from partial:
$('#content').html('<%= escape_javascript render("layouts/galleries/show") %>');
And controller that operates with models and renders html and js:
class GalleriesController < ApplicationController
def show
#galleries = Gallery.all
#gallery_to_show = Gallery.find(params[:id])
respond_to do |format|
format.html
format.js
end
end
end
Ajax works fine, but I try to put callback after ajax completed:
jQuery(function() {
$(".link-to-gallery").bind("ajax:complete", function() {
alert(1)
});
});
and alert never shows. What am I doing wrong? Rails version is 3.2.11, Ruby version is 1.9.3p194
Update: When I'm using this code
jQuery(function() {
$(".link-to-gallery")
.on("ajax:before", function () {
alert("before")
})
.on("ajax:complete", function() {
alert("complete")
});
});
"before" alert fires but only once. If I press again I gain nothing. But ajax still works.

I think the problem is with your controller method that is not responding the async call with a success status message, 200.
Try this
def show
#galleries = Gallery.all
#gallery_to_show = Gallery.find(params[:id])
respond_to do |format|
format.html { :status => 200 }
format.js { :status => 200 }
end
end
If that doesn't work, try this.
def show
#galleries = Gallery.all
#gallery_to_show = Gallery.find(params[:id])
respond_to do |format|
format.html { :status => :ok }
format.js { :status => :ok }
end
end

It seems that I'm lame but smart enough to fix this. I had these links:
<%= link_to g.name, g, :class => 'link link-to-gallery', :remote => true %>
in the partial which gets re-rendered after ajax. So the callback functions that were attached to these links were flushed away after ajax. So I put link out of this partial and it works now.

Related

Cannot get page to redirect?

I'm using Rails 4 and Dropzone.js to drag and drop files and upload them on form submission. I don't know why I can't get this to work but I'm trying to redirect after the form submits to a certain page but its not doing it (everything saves correctly though).
Here is my code:
items/new.html.haml > _form.html.haml
= form_for #item, validate: true,
html: {id: 'item-form', class: 'form-horizontal form', multipart: true} do |f|
= f.text_field :name
%main#image-preview
#dropzone
.fallback
= f.file_field :image, multiple: false
= f.submit 'Done', id: 'item-submit'
items.coffee
Dropzone.autoDiscover = false
if document.getElementById('item-form')
dropzone = new Dropzone('#item-form',
maxFiles: 1
maxFilesize: 1
paramName: 'item[image]'
headers: "X-CSRF-Token" : $('meta[name="csrf-token"]').attr('content')
addRemoveLinks: true
clickable: '#image-preview'
previewsContainer: '#image-preview'
thumbnailWidth: 200
thumbnailHeight: 200
autoProcessQueue: false
uploadMultiple: false)
$('#item-submit').on 'click', (e) ->
e.preventDefault()
e.stopPropagation()
if dropzone.getQueuedFiles().length > 0
dropzone.processQueue()
else
$getScript '/items'
return
items_controller.rb
def continue
#item = Item.find(params[:id])
if #item.user_id == current_user.id
respond_to do |format|
format.html
format.xml
format.json { render :json => {} }
end
end
end
def new
#item = current_user.items.build
end
def create
#item = current_user.items.build(item_params)
respond_to do |format|
if #item.save
format.json { render :json => "window.location = #{post_continue_item_path(#item).to_json}" }
else
format.html { render :new }
format.json { render json: #item.errors, status: :unprocessable_entity }
end
end
end
routes.rb
resources :items do
get '/post/continue', to: 'items#continue', on: :member
end
log
Started POST "/items" for 127.0.0.1 at 2015-10-06 12:23:35 -0700
Processing by ItemsController#create as JSON
............
Completed 200 OK in 1786ms (Views: 0.2ms | ActiveRecord: 10.6ms)
Not sure where to go with this so how do I redirect when its giving me a JSON call?
JSON is not Javascript. It is designed to pass some data, not a working code. Check the response with your browser's developer tools, you will see your 'window.location' script nicely wrapped and basically unable to do anything - it should come as a mere string.
If you want a pure, classical HTTP redirect, you should look into redirect_to Rails method as your only response, and never try to render a JSON when you actually need a redirect.

Rails: Manipulate rendered JSON when using UJS

I enhanced my app by allowing AJAX form submissions, using UJS. Here is my create#product action:
def create
if Product.create params[:product]
respond_to do |format|
message = "New product created."
format.html { redirect_to :back, :notice => message }
format.js { render :json => { :status => true, :message => message } }
end
end
end
But I'm figuring out how to handle outputted JSON in my views/products/create.js.erb file??
I tried this simple console.log example, but without success (I mean, no console output):
$(function(){
console.log(xhr.responseText);
});
Thanks in advance.
You could use:
$('form.new_product').bind('ajax:success',function(event, data, status, xhr){
});
$('form.new_product').bind('ajax:error',function(event, xhr, status, error){
});
or even $('form.new_product').on(same_args).
Just make sure new_product is the actual class of your form.

How to make AJAX responses work from the Rails side?

The HTML form:
<form id="newsletter" method="post" action="/subscribers" data-remote="true">
<label for="email">Enter your email:</label>
<input type="text" name="email" class="text" />
<p class="btn"><span>Signup</span></p>
</form>
Note the data-remote="true"
The Controller:
class SubscribersController < ApplicationController
def create
#subscriber = Subscriber.create(:email => params[:email],
:ip_address => request.remote_ip )
respond_to do |format|
format.js
end
end
end
The View (subscribers/create.js.erb)
no clue what goes here to make it return normal AJAX response (or error if it encountered one
1. What do i put in the view to make it return normal ajax response or error? -- Is it even needed to begin with (can I return this without creating such views)
2. Is this the correct way of doing ajax with Rails?
This looks exactly like a question that I just answered today for another user... same model names and everything.
def create
#subscriber = Subscriber.new(#your params)
respond_to do |format|
if #subscriber.save
format.js { render :json => #subscriber, :status => :created, :location => #susbscriber }
else
format.js { render :json => #susbcriber.errors, :status => :unprocessable_entity }
end
end
end
Also, you shouldn't have to do the unless Subscriber.find_by_email(params[:email]) in your controller. You should just add validates_uniqueness_of :email to the Subscriber model.
In the .erb file that contains the form, you would add the following javascript:
jQuery(function($) {
// create a convenient toggleLoading function
var toggleLoading = function() { $("#loading").toggle() };
$("#your-form")
.bind("ajax:loading", toggleLoading)
.bind("ajax:complete", toggleLoading)
.bind("ajax:success", function(event, data, status, xhr) {
$("#response").html(data);
});
.bind("ajax:failure", function(event, data, status, xhr) {
//your code
});
});
A standard respond_to block (this allows both html and js) would be:
respond_to do |format|
if #subscriber.save
format.html { redirect_to(#subscriber, :notice => 'Subscriber created.') }
format.js # Not redirecting, just spitting out the JSON(js?) response (I believe).
else
format.html { render :action => "new" }
format.js # Not redirecting for js and this time return error response.
end
end
So what you have actually looks ok to me. Is it working ok or is there an issue?
The above should work with rails2 and rails3. Rails3 has a more succint syntax (of course) but given you are Rails2 I'll leave that for now.

ajax request with form_remote_tag doesn't work

So I'm using a form_remote_tag to attempt an ajax form submission, like so:
<% form_remote_tag :update=> 'test', :url=> {:action=>'test_action'} do -%>
It renders with no apparent problem:
<form action="/pages/test_action" method="post" onsubmit="new Ajax.Updater('test', '/pages/test_action', {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
The test_action action:
def test_action
if request.xhr?
render :text => 'some text'
else
puts 'nope'
end
end
When I submit the form(via the submit button, nothing weird like the jquery submit() event), no ajax request is made. The xhr check returns false. Help please??
In controller you should respond to specified format, js in your case. For example:
def create
#item = Item.new(params[:item])
respond_to do |format|
if #item.save
flash[:notice] = 'Item was successfully created.'
format.js
format.html { redirect_to(#item) }
format.xml { render :xml => #item, :status => :created, :location => #item }
else
format.html { render :action => "new" }
format.xml { render :xml => #item.errors, :status => :unprocessable_entity }
end
end
end
The best practice for now is to use unobtrusive javascript (UJS). There is no form_remote_tag in rails 3. UJS can be used with rails 2.3 as well.

Ajax and vote_fu | missing before statement

relate question: Vote_fu and Ajax requests
There seems to be something wrong with my Ajax request.
What I 'm trying to do is on event click vote submit a vote then update page with out refreshing the page.
votes_controller.rb:
def create
#album = Album.find(params[:album_id])
respond_to do |format|
if current_user.vote(#album, params[:vote])
format.js { render :action => "create", :vote => #vote }
format.html { redirect_to([#album.user, #album]) }
#format.xml { render :xml => #album, :status => :created, :location => #album }
else
format.js { render :action => "error" }
format.html { render :action => "new" }
format.xml { render :xml => #vote.errors, :status => :unprocessable_entity }
end
end
end
link | for view album show :
<%= link_to_remote "Vote Up",
:url => user_album_votes_path(album.user, album,
:vote => :true, :format => :js),
:method => :post %>
application.js
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
jQuery(document).ready(function() {
$("#votes_.album").bind('click');
})
create.js
page.replace_html "#votes_{#album.id}",
:partial => "album_vote",
:locals => {:album => #album}
This is the following error message which I'm getting:
missing ; before statement
[Break on this error] page.replace_html "#votes_#{#album.id}", ...bum_vote", :locals => {:album => #album}
I'm not sure what is going wrong here I have been following many example from the vote_fu doc's
still having problems.
http://github.com/peteonrails/vote_fu/tree#readme
one amendment made on create.js
there is now another error:
No the error has moved over to the votes_controller
NoMethodError (You have a nil object when you didn't expect it!
<br />
The error occurred while evaluating nil.vote):
app/controllers/votes_controller.rb:53:in `create'
app/controllers/votes_controller.rb:52:in `create'
<br />
Rendered rescues/_trace (128.4ms)
Rendered rescues/_request_and_response (0.4ms)
Rendering rescues/layout (internal_server_error)
These lines are on the create action, which looks perfectly fine!?
How do I get this to work?
Regard
Dan
Try changing the create.js to
page.replace_html "#votes_#{#album.id}", :partial => "album_vote", :locals => {:album => #album}
You might have missed the # for the variable string interpolation.
Solved!
The problem was that I didn't add a before statement to refresh the vote count!
so I did and it worked as well as that, I changing the create.js to create.sj.erb, also I made some small changes to my application.js file. After all that I then added a flash[:note] = you have voted!, then added a function to remove the flash notice after a sec and fadeOut!
For anyone who's interested heres the code:
Application.js
jQuery(document).ready(function() {
$("#vote").bind('click', function(e) {
if (e.target.tagName == "DIV") {
$(this).find(".album_extened").toggle('blind');
}
})
})
create.js.erb
$("#vote").before('<div id="notice"><%= escape_javascript(flash.delete(:notice)) %></div>');
$("#vote_count").html("<%= #album.votes_for - #album.votes_against %>");
$(document).ready(function() {
setTimeout(hideFlashMessages, 1000);
});
function hideFlashMessages() {
$("#vote, #notice").append('').fadeOut(1000);
}
If anyone knows a better why which this can be done please forward!!
A good viewing of [http://railscasts.com/episodes/136-jquery][1]
Reading of [link text][2]
Soon fixed things Thanks Jonathanlink text
[1]: http://railscasts.com/episodes/136-jquery/"Rails Cast ep 136"
[2]: http://www.notgeeklycorrect.com/english/2009/05/18/beginners-guide-to-jquery-ruby-on-rails/"Beginners Guild to jQuery and Rails"
and Thanks Sam for being helpful!!
It seems to me that the current_user in the create method did not get its value set.
How do you set the current_user value? In other plugins, they usually define this as an
instance method or instance variable with accessor.
So maybe changing the create method to the following might help:
def create
#album = Album.find(params[:album_id])
respond_to do |format|
if #current_user.vote(#album, params[:vote])
format.js { render :action => "create", :vote => #vote }
format.html { redirect_to([#album.user, #album]) }
#format.xml { render :xml => #album, :status => :created, :location => #album }
else
format.js { render :action => "error" }
format.html { render :action => "new" }
format.xml { render :xml => #vote.errors, :status => :unprocessable_entity }
end
end
end
You might have missed the # before the current_user.vote

Resources