1

I have a form in modal bootstrap (pop up). The problem is that when the form is not cleaned by Django, the errors are written in red below the form fields but the modal closes.

The user think the form is validate but no.

My form :

class signupForm(forms.Form):
     username = forms.CharField(max_length=25)
     mail = forms.EmailField(label="Email", max_length=82)
     password = forms.CharField(max_length=50)

def clean_mail(self):
    mail = self.cleaned_data['mail']
    testMail = User.objects.filter(email=mail)
    if len(testMail)>0:
        raise forms.ValidationError("Already used.")
    return mail

The view :

def signup(request):

    if request.method == "POST":
        form = signup(request.POST)
        if form.is_valid():
            mail = form.cleaned_data["mail"]
            username = form.cleaned_data["username"]
            password = form.cleaned_data["password"]
            u = User.objects.create_user(username,mail,password)
            u.save()
            the_user = authenticate(username=username, password=password)
            login(request,the_user)
            return redirect(...)
        else :
            error = True
    else :
        form = signupForm()
    return render(request,...)

Finally the most important, the template :

<a href="#" data-toggle="modal" data-target="#myModal"><i> Signup </i></a>

    <div id="myModal" class="modal fade" role="dialog">
            <div class="modal-dialog">


                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">&times;</button>
                        <h3 class="modal-title"> <b> Signup </b> </h3>
                    </div>
                    <div class="modal-body">
                        {% load bootstrap %}
                        <form method="POST" action="{% url 'signup' %}" class="">
                            {% csrf_token %}

                            <div class="row">
                                <div class="col-md-offset-2 col-md-8">
                                    {{ formSignup|bootstrap }}
                                </div>
                            </div>

                            <div class="div-button">
                                <input type="submit" class="btn btn-info" value="Sign up">
                            </div>
                        </form>
                    </div>
                    <div class="modal-footer">
                        <button type="button" class="btn btn-default" data-dismiss="modal">Quit</button>
                    </div>
                </div>

            </div>
        </div>

How to keep the signup form (modal bootstrap) when the form is not cleaned ?

Zoulou
  • 303
  • 2
  • 16

1 Answers1

0

I also ran into this issue. I was able to resolve the issue by referencing this post (to add "has-error" to the offending Form input). Note, I'm using Crispy Forms and AJAX form submission.

The Form:

class SomeForm(models.ModelForm):

def __init__(self, data=None, *args, **kwargs):
    super(SomeForm, self).__init__(data, *args, **kwargs)

    self.helper = FormHelper()
    self.helper.form_class = "form-horizontal"
    self.helper.form_id = "id_some_form"
    self.helper.form_action = reverse('some-form-url')
    self.helper.label_class = 'col-md-4'
    self.helper.field_class = 'col-md-6'
    self.helper.layout = Layout(
        Fieldset('The Details',
                 'field1',
                 'field2',
                 ),
        Fieldset('',
                 Div(
                     Button('cancel', 'Cancel', css_class='btn btn-danger', data_dismiss="modal"),
                     Submit('submit', 'Create', css_class='btn btn-success'),
                     css_class='col-md-10 text-right',
                 ),
        ),
    )

The View:

    form = SomeForm(request.POST)

    if form.is_valid():
        ...
    elif form.non_field_errors():
        form.helper['field2'].wrap(Div, css_class="has-error")

The HTML in a template that triggers the Modal form:

                            <button class="btn btn-xs btn-success"
                                onclick="launchModalForm(this)"
                                data-title="Add New Thing"
                                data-target-url="{% url 'thing-create' %}"
                                data-success-url="{% url 'thing-list' %}">

                            <span class="glyphicon glyphicon-plus-sign"></span>
                            Add Thing
                        </button>

Note: The "data-target-url" attribute should be the URL that triggers the View that instantiates the Form. The "data-success-url" attribute should be the URL to redirect to after successful form submission.

The Template to render the form in the Modal window:

    {% load crispy_forms_tags %}
    {% crispy form %}

The Javascript for AJAX form render/submission in a Bootstrap Modal window:

var formAjaxSubmit = function(form, modal, success_url) {
    $(form).submit(function (e) {
        e.preventDefault();
        $.ajax({
            type: $(this).attr('method'),
            url: $(this).attr('action'),
            data: $(this).serialize(),
            success: function (xhr, ajaxOptions, thrownError) {
                if ( $(xhr).find('.has-error').length > 0 ) {
                    $(modal).find('.modal-body').html(xhr);
                    formAjaxSubmit(form, modal, success_url);
                } else {
                    // $(modal).modal('toggle');
                    window.location.href = success_url;
                }
            },
            error: function (xhr, ajaxOptions, thrownError) {
            }
        });
    });
};
window.launchModalForm = function(value) {
    var modal_title = $(value).attr('data-title');
    var modal_target_url = $(value).attr('data-target-url');
    var success_url = $(value).attr('data-success-url');
    $('.modal-title').text(modal_title);
    $('#form-modal-body').load(modal_target_url, function () {
        $('#form-modal').modal('toggle');
        formAjaxSubmit('#form-modal-body form', '#form-modal', success_url);
    });
};
Community
  • 1
  • 1
cgonchar
  • 21
  • 3