stockersky
stockersky

Reputation: 1571

Django ajax POST works but then the page is stalled because it does not hit next GET

Here is my use case : My views displays an inline formset (formset associated to modelform). The view will display each object created by the user and allow him to modify them through the form. The user stays on the same page (i post on the same page).

This works without Ajax.

But as the user may create many objects, using Ajax would prevent the page from reloading after each submit.

I implemented Ajax. It works on the first submit. But then, the page looks stalled : i cannot submit anymore.

NOTE about the strategy used : the main template (education_form.html) {% include %} the form template (education_form_inner.html). Jquery replaceWith() replace the rendered_to_string oject as html.

While adding some print statements in my view, i realized that the else part after the POST is never executed (those stating the two last 'print')...

Here is my view :

def education_edit(request, pk):

    curriculum_inst=get_object_or_404(Curriculum, pk=pk)

    EducationFormSet = inlineformset_factory(Curriculum, Education,
                          form=EducationForm,
                          extra=1, max_num=15, can_delete=True)

    if request.method == 'POST' and request.is_ajax():
        education_formset = EducationFormSet(request.POST, prefix='form',
                               instance=curriculum_inst)

        if education_formset.is_valid():
            education_formset.save()
            html = render_to_string(
                       'cv_frontend/education_form_inner.html',
                       {'formset': education_formset}
                    )
            payload = {
                'result': 'success',
                'message': 'Form valid',
                'form': html
            }
        else:
            html = render_to_string(
                       'cv_frontend/education_form_inner.html',
                       {'formset': education_formset}
                   )
            payload = {
                'result': 'error',
                'message': 'Form invalid',
                'form': html
            }
        print('>>>>>>>>>>>> AJAX POST')
        return JsonResponse(payload)

    else:
        print('>>>>>>>>>>>> prepare object')
        education_formset = EducationFormSet(prefix='form', instance=curriculum_inst)

    print('>>>>>>>>>>>> GET')
    return render(request, 'cv_frontend/education_form.html',
                  {'formset': education_formset})

Here is the JS :

$(document).ready(function() {
$('form').submit(function(event) {
    event.preventDefault();
    console.log('AJAXXX!!!');
    var $myForm = $(this);

    var $formData = $myForm.serialize();
    console.log('les datas : ')
    console.log($formData);

    var $thisURL = $myForm.attr('data-url') || window.location.href // or set your own url
    console.log("l'url : ")
    console.log($thisURL)

    $.ajax({
        method: $myForm.attr('method'),
        url: $thisURL,
        data: $formData,
        dataType : 'json',
        success: handleFormSuccess,
        error: handleFormError,
    })


    function handleFormSuccess(data, textStatus, jqXHR){
        console.log(data.form)
        console.log(textStatus)
        console.log(jqXHR)
        console.log('OKKKK')
        $true_html = $(data.form).html()
        $myForm.replaceWith($true_html)
        // location.reload();

    }

    function handleFormError(jqXHR, textStatus, errorThrown){
        console.log(jqXHR)
        console.log(textStatus)
        console.log(errorThrown)
        console.log('KKKKOO')
    }
});

});

Actually, if i uncomment the 'location.reload()' instruction, this would work. But all the validation errors on the page would be flushed (this is normal).

Thanks for you help!

Upvotes: 0

Views: 60

Answers (1)

kip
kip

Reputation: 1140

This is because you use .replaceWith() when the first AJAX POST is success and the event attached on your form(original) element is gone because you replace all the html, in this case you need tou use Event delagation

$('body').on('submit', 'form', function (e) {

BTW

$true_html = $(data.form).html() this line is unnecesary, if the value of the data.form is a valid HTML you dont need tell to jQuery that create an entire object and then get the htmlString, use replaceWith directly $myForm.replaceWith(data.form) or $myForm.html(data.form).

Upvotes: 1

Related Questions