2

I'm trying out AJAX submission for the PT Contact Form for the first time. I've managed to get errors appearing on the frontend, but I don't feel like I'm doing it the right way. It also doens't integrated at all with the {% macro errorList(errors) %} code that comes with the form. This is my form JS:

$(function(){
    $('#ajax-form').submit(function(ev) {
        // Prevent the form from actually submitting
        ev.preventDefault();

        // Get the post data
        var data = $(this).serialize();

        // Send it to the server
        $.post('/', data, function(response) {
            if (response.success) {
                $('#thanks').fadeIn();
            } else {
                // response.error will be an object containing any validation errors that occurred, indexed by field name
                // e.g. response.error.fromName => ['From Name is required']
                if (response.error.fromName) {$('ul.errors').append('<li>'+response.error.fromName+'</li>');}
                if (response.error.fromEmail) {$('ul.errors').append('<li>'+response.error.fromEmail+'</li>');}
                if (response.error.subject) {$('ul.errors').append('<li>'+response.error.subject+'</li>');}
                if (response.error.message) {$('ul.errors').append('<li>'+response.error.message+'</li>');}
            }
        });
    });
});

Form code:

{% macro errorList(errors) %}
{% if errors %}
<ul class="errors">
    {% for error in errors %}
    <li>{{ error }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endmacro %}

{% from _self import errorList %}

<form method="post" action="" accept-charset="UTF-8" id="ajax-form">
    {{ getCsrfInput() }}
    <input type="hidden" name="action" value="contactForm/sendMessage">
    <input type="hidden" name="redirect" value="/contact">

    <label for="fromName">Name *</label>
    <input class="form-control" id="fromName" type="text" name="fromName" value="{% if message is defined %}{{ message.fromName }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('fromName')) }}

    <label for="fromEmail">Email *</label>
    <input class="form-control" id="fromEmail" type="text" name="fromEmail" value="{% if message is defined %}{{ message.fromEmail }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('fromEmail')) }}

    <label for="subject">Subject</label>
    <input class="form-control" id="subject" type="text" name="subject" value="{% if message is defined %}{{ message.subject }}{% endif %}">
    {{ message is defined and message ? errorList(message.getErrors('subject')) }}

    <label for="message">Message *</label>
    <textarea class="form-control" rows="10" cols="40" id="message" name="message">{% if message is defined %}{{ message.message }}{% endif %}</textarea>
    {{ message is defined and message ? errorList(message.getErrors('message')) }}

    <button type="submit" class="btn btn-primary">Submit</button>
</form>

<ul class="my-errors"></ul>

I've had to put a blank <ul class="my-errors"></ul> under my form, as the .error ul that comes with the contact form doesn't appear. Where am I going wrong?

Desired result: I get exactly the same error handling as I would if I wasn't submitting via AJAX - i.e., the error messages relating to specific fields appear under those fields in the form.

1 Answer 1

5

If you want the error messages to be displayed identical to P&T's template/macro default, this should do the trick:

$(function(){
    $('#ajax-form').submit( function(ev) {

        // Prevent the form from actually submitting
        ev.preventDefault();

        // Remove any existing error messages from previous attempts
        $(this).find( '.errors' ).remove();

        // Get the post data
        var data = $(this).serialize();

        // Send it to the server
        $.post('/', data, function(response) {

            if (response.success) {

                // All good!
                $('#thanks').fadeIn();

            } else {

                // Loop through the errors and append to relevant fields
                for ( var fieldId in response.error ) {

                    // Create the <ul>
                    var $errors = $( '<ul class="errors" />' );

                    // Wrap the error messages in <li> tags
                    var messages = $.map(response.error[fieldId], function(message){
                        return '<li>' + message + '</li>';
                    });

                    // Append the error messages to the ul
                    $errors.append( messages.join( '' ) );

                    // Select the input element and append the .errors <ul> after it.
                    $('#'+fieldId).after($errors);

                }

            }
        });
    });
});

Just to be clear though, the PT Contact Form template doesn't force you to display your error messages in any given way; both the contact form template as a whole, and specifically how error messages are displayed (both the template macro for non-Ajax requests and the stuff in the response.error object) is obviously totally up to you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.