views:

87

answers:

2

The first submit works as expected, but the next time it's fully posted back. I'm using jQuery.form plugin, specifically the .ajaxSubmit(options) call to submit the form. There are a couple levels of wrapper div's, but I debug the button.click binds and I can't figure out why the second time, even with the same variables, it does a full post and my partial view is returned on a brand new page.

here, buttonid and screenid are the same on both posts. I indicate this because they're calculated as per a naming convention like <name>Outer (wrapper), <name> (update target), and <name>Form (form to be submitted)

$('.formButton').click(function () {
    var buttonid = $(this).attr('id');
    var screenid = $('#' + buttonid).closest('div:not(.CSRForm)').attr('id').replace('Outer', '');
    //appends a hidden element so I know which button was pressed when posted
    $('#' + screenid + 'Form').append('<input type="hidden" name="submitButton" value="' + buttonid.replace(screenid, '') + '" />');
    $('#' + screenid + 'Form').submit();
}); 

mind the .formButton elements are not inside the form, which is why I had to bind the submit event as such. My partial view only returns the form and not the buttons (they are dynamic)

here is the .ajaxSubmit:

$('.CSRForm').submit(function () {
    var needsValidation = "yes";
    if (needsValidation) {
        $(this).ajaxSubmit({
            target: '#AccountSetup',
            replaceTarget: false,
            success: StepCallWithForm //to check whether the response is valid for redirecting
        });
        return false;
    }
}); 

and my MVC action if it's relevant:

    public ActionResult AccountSetup(AccountSetupViewModel vm, string submitButton)
    {
        if (!ModelState.IsValid)
        {
            return PartialView(vm);
        }
        else
        {
            return Content(submitButton + ",AccountSetup");
        }
    }

Edit: After inserting this line immediately inside my $(function() {:

$('#AccountSetup').ajaxForm();

I was able to stop the full postback. In Firebug, now I see ajax postback to /CSR/Home/CSR? which is where all this stuff is to begin with. It's like the form lost its action property. Are my events somehow crossfiring?

+2  A: 

This could happen if you replace the original form in the success callback with the partial view.

So when you remove some HTML elements (as in replace existing HTML with partial view from the server) all their events are gone as well. Re-adding the same HTML (from your point of view) is just some new HTML to the browser. It doesn't make assumptions whether this new HTML is related to old code or not. That's why you have to re-add all functionality and events if you want the new form to work as it did before.

If this is your case the form will no longer have the submit Ajax action attached and therefore the second time it will perform a full post. For this to work you need to reattach the submit event in the success function:

$(function() {
    ajaxifyForm();
});

function ajaxifyForm() {
    $('#AccountSetup').ajaxForm({
        target: '#AccountSetup',
        replaceTarget: false,
        success: stepCallWithForm
    });
}

function stepCallWithForm(result) {
    // If you replace the #AccountSetup form with the 
    // returned partial result you need to reattach the AJAX submit:
    ajaxifyForm();
}
Darin Dimitrov
I'd add additional info: *"When you removed existing HTML (your form) all it's elements and their events were removed as well. So when re-adding the same HTML (could be anything basically) you have to re-manipulate it as well (attaching events and similar)."* This would explain the situation even better why he has to reattach events.
Robert Koritnik
@Robert, good point, feel free to edit my post to include this valuable information.
Darin Dimitrov
I should point out that I have multiple forms on this page with the class `.CSRForm`, so should I use Sohnee's solution instead? **Or**, could I use the `$form` parameter in the .ajaxSubmit success callback? I mentioned this parameter in a recent post, specifically that I wasn't sure how it was used, but maybe it's the new form. Sohnee's solution sounds simpler--like I could bind it once and forget it.
David
I tried both ways, and `.live` was definitely the least amount of code. Thanks!
David
A: 

Instead of binding to the click event, you could use jQuery's live() event binding, which survives AJAX loading. You can do this by replacing:

$('.formButton').click(function () {

With

$('.formButton').live("click", function () {
Sohnee