I want to start using the Ajax events ajax:success, ajax:failure, ajax:complete and ajax:beforeSend as recommended for unobtrusive Javascript in posts like:
- http://www.simonecarletti.com/blog/2010/06/unobtrusive-javascript-in-rails-3/
- http://www.alfajango.com/blog/rails-3-remote-links-and-forms/
But for some reason it's not working for me. I am missing something (something small) as I cannot get the events to trigger my Javascript. I am hoping someone could spot the "obvious" mistake/omission in my code.
Some details on my environment:
- Rails 3.1
- jQuery (jquery-rails gem)
- therubyracer for server side js processing (not that it should matter for my example)
To try and work out what I am missing I have created a simple test application which has a single remote button to. When the button is clicked, I want alert bo开发者_StackOverflowxes to fire. The code of this app can be seen on github here:
http://github.com/jpmcgrath/rbtest
I have deployed the application to heroku here:
http://rbtest.heroku.com/projects/
If you look at the app, you can click the button and the button successfully creates a new project (to see it manually refresh), but ajax:success event doesn't seem to happen?
The guts of the code is as follows:
In projects_controller.rb
def remote_test
@project = Project.new(:name => "remote test")
respond_to do |format|
if @project.save
puts "project saved!\n\n\n"
format.html { redirect_to @project, notice: 'Project was successfully created.' }
format.json { render json: @project, status: :created, location: @project }
else
format.html { render action: "new" }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end
In application.js
jQuery(document).ready(function() {
jQuery(".remote_button").click(function() {
alert('Handler for .click() called.');
})
.bind("ajax:complete", function() {
alert('complete!');
})
.bind("ajax:beforeSend", function () {
alert('loading!');
})
.bind("ajax:error", function (xhr, status, error) {
alert('failure!');
})
.bind('ajax:success', function(event, data, status, xhr) {
alert('success!');
});
});
In the view projects/index.html.erb
<%= button_to "remote test", remote_test_path, :remote => true, :class => 'remote_button' %>
If anyone could point out what I am missing (I suspect it has something to do with response type) it would be greatly appreciated.
The reason your event handler is not firing is because your selector is on the wrong element. button_to creates a form with a single input tag, and it's that input tag that has the class your selecting on, but the ajax events are triggered on the form, not the input tag.
Try this
jQuery(document).ready(function() {
jQuery(".remote_button").click(function() {
alert('Handler for .click() called.');
});
jQuery("form.button_to").bind("ajax:complete", function() {
alert('complete!');
})
.bind("ajax:beforeSend", function () {
alert('loading!');
})
.bind("ajax:error", function (xhr, status, error) {
alert('failure!');
})
.bind('ajax:success', function(event, data, status, xhr) {
alert('success!');
});
});
I did the equivalent in my firebug console and it fired the ajax:success handler when the callback was on the form.
To change the class on the form use the :form_class option to change it from button_to to something else
<%= button_to "remote test", remote_test_path, :remote => true, :class => 'remote_button', :form_class => 'remote_button_form' %>
Then add your ajax callbacks using
jQuery(".remote_button_form").bind ...
http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to
Rails has changed how javascript files are handled.
Railscasts has a few examples.
http://railscasts.com/episodes/279-understanding-the-asset-pipeline
http://railscasts.com/episodes/267-coffeescript-basics?autoplay=true
精彩评论