How to (re)bind to submit button/form on .load(ed) form
During early in learning how to implement unobtrusive js (using Rails & jQuery) I've run into an issue of how to (re)bind a submit button/form after .load(ing) new content that includes a form.
I've set up a 'create new item' form to show at the top of a lising of items (when the user clicks on a create button)
sale_case/show/开发者_Python百科_requirments_new.html.haml:
- form_for ([@sale_case, @sale_case_requirement]), :html => { :id => 'requirement_form', :class => "submit-with-ajax"} do |f|
...
%button{ :type => "submit" } Save Requirement
application.js:
jQuery(document).ready(function() {
jQuery(".submit-with-ajax").submitWithAjax();
}
...
jQuery.ajaxSetup({
'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
jQuery.fn.submitWithAjax = function() {
this.submit(function() {
jQuery.post(this.action, jQuery(this).serialize(), null, "script");
return false;
})
return this;
};
requirements_controller.rb:
def create
@sale_case_requirement = @sale_case.requirements.new(params[:requirement])
if @sale_case_requirement.save
@message = "Success..."
@success = true
#...
respond_to do |format|
format.js
end
end
requirements/create.js.erb:
mesg("<%= @message %>");
<%- if @success %>
jQuery("#requirement_form")[0].reset();
jQuery('#requirements').load('<%= requirements_view_sale_case_requirements_path(@sale_case.id) %>' );
<% end %>
It's all working well the first time around unobtrusively. The problem comes when the user creates the second item (on the form loaded via ajax). The button is not getting bound to the submitWithAjax function. How do you do that when .load(ing) content?
I ended up having to do this in the partial (obtrusive) in order to get it to work, but it bugs me not to be able to figure this out. :
%button{ :type => "submit", :onclick => "jQuery.post('#{sale_case_requirements_path(@sale_case.id, @sale_case_requirement.id)}', jQuery('#requirement_form').serialize(), null, 'script'); return false;"} Save Requirement
Here's what I ended up changing in the code based on Ender's input. I got an error with finding 'submitWithAjax' with his version of the code, but he pointed me in the right direction and after reading the .live documentation I came up with this which works:
application.js
jQuery(document).ready(function() {
# Just put it all in one place
jQuery(".submit-with-ajax").live('submit', function() {
jQuery.post(this.action, jQuery(this).serialize(), null, "script");
return false;
});
...
}
sale_case/show/_requirments_new.html.haml:
# Change the button back to unobtrusive
%button{ :type => "submit"} Save Requirement
Thanks!
Change this original code:
jQuery(document).ready(function() {
jQuery(".submit-with-ajax").submitWithAjax();
}
to this:
jQuery(document).ready(function() {
jQuery(".submit-with-ajax").live('submit', submitWithAjax);
}
and this original code:
jQuery.fn.submitWithAjax = function() {
this.submit(function() {
jQuery.post(this.action, jQuery(this).serialize(), null, "script");
return false;
})
return this;
};
to this:
jQuery.fn.submitWithAjax = function() {
jQuery.post(this.action, jQuery(this).serialize(), null, "script");
return false;
};
The jQuery .live() call binds the named handler to the named event on all current and future elements that match the given selector, including elements that are loaded in via ajax. Hopefully that does what you're looking for.
See the following for documentation on the .live() function: http://api.jquery.com/live/
精彩评论