Running a custom function if Contact Form 7 returns an invalid field on AJAX submit

15.1k views Asked by At

I'm using the WordPress plugin Contact Form 7 and I need to manipulate some data if there is an error on a specific field, not sure if this can be done with hooks or anything as I need to run some JavaScript code and not PHP, so I'm assuming I would need to attach a onclick event when the user attempts to submit the form?

If it can be done with a hook someway I assume it would be done with this one.

If it can be done with a hook, what is the best way to achieve this? If not, I guess it would be easy enough to attach an onclick event to the button, but I'm unsure how I can get it to run only if there is a validation error and after the CF7 JS code has already run?

The HTML of the form:

<div role="form" class="wpcf7" id="wpcf7-f1304-p10-o1" lang="en-US" dir="ltr">
    <div class="screen-reader-response"></div>
    <form name="" action="/freetrademarksearch/#wpcf7-f1304-p10-o1" method="post" class="wpcf7-form" enctype="multipart/form-data" novalidate="novalidate">
        <div style="display: none;">
            <input type="hidden" name="_wpcf7" value="1304" />
            <input type="hidden" name="_wpcf7_version" value="4.1.2" />
            <input type="hidden" name="_wpcf7_locale" value="en_US" />
            <input type="hidden" name="_wpcf7_unit_tag" value="wpcf7-f1304-p10-o1" />
            <input type="hidden" name="_wpnonce" value="a2009d4694" />
        </div>
        <div class="field_wrapper">
            <p class="title">Trademark to be searched</p>
            <div class="field">
                <span class="wpcf7-form-control-wrap trademark"><input type="text" name="trademark" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required form-control" aria-required="true" aria-invalid="false" /></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Upload Logo <span class="optional">(optional)</span></p>
            <div class="field">
                <div class="btn browse_btn">
                    <span class="wpcf7-form-control-wrap logo"><input type="file" name="logo" value="1" size="40" class="wpcf7-form-control wpcf7-file" aria-invalid="false" /></span>
                </div>
                <div class="wp_is_annoying">
                    <span id="upload_filename" class="file_chosen">No file selected</span>
                </div>
                </p>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Goods/Services the trademark is, or will be, used to identify</p>
            <div class="field">
                <span class="wpcf7-form-control-wrap identify"><input type="text" name="identify" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required form-control" aria-required="true" aria-invalid="false" /></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">If you already promote this in Australia, what was the first date of promotion?</p>
            <div class="field">
                <span class="wpcf7-form-control-wrap date-promoted"><input type="text" name="date-promoted" value="" size="40" class="wpcf7-form-control wpcf7-text form-control" aria-invalid="false" /></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Has promotion been continuous since the above date?</p>
            <div class="field radio_btns">
                <div class="holder">
                    <span class="wpcf7-form-control-wrap continuous_promotion"><span class="wpcf7-form-control wpcf7-radio" id="yes_continuous_promotion"><span class="wpcf7-list-item first last"><label><input type="radio" name="continuous_promotion" value="Yes" />&nbsp;<span class="wpcf7-list-item-label">Yes</span></label></span></span></span>
                </div>
                <div class="holder">
                    <span class="wpcf7-form-control-wrap continuous_promotion"><span class="wpcf7-form-control wpcf7-radio" id="no_continuous_promotion"><span class="wpcf7-list-item first last"><label><input type="radio" name="continuous_promotion" value="No" />&nbsp;<span class="wpcf7-list-item-label">No</span></label></span></span></span>
                </div>
                </p>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Full Name</p>
            <div class="field half">
                <span class="wpcf7-form-control-wrap first-name"><input type="text" name="first-name" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-validates-as-required first form-control" aria-required="true" aria-invalid="false" placeholder="First Name" /></span><span class="wpcf7-form-control-wrap last-name"><input type="text" name="last-name" value="" size="40" class="wpcf7-form-control wpcf7-text form-control" aria-invalid="false" placeholder="Last Name" /></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Email Address:</p>
            <div class="field">
                <span class="wpcf7-form-control-wrap email"><input type="email" name="email" value="" size="40" class="wpcf7-form-control wpcf7-text wpcf7-email wpcf7-validates-as-required wpcf7-validates-as-email form-control" aria-required="true" aria-invalid="false" /></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Phone Number:</p>
            <div class="field">
                <span class="wpcf7-form-control-wrap phone"><input type="text" name="phone" value="" size="40" class="wpcf7-form-control wpcf7-text form-control" aria-invalid="false" /></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">Comment: <span class="optional">(optional)</span></p>
            <div class="field">
                <span class="wpcf7-form-control-wrap comments"><textarea name="comments" cols="40" rows="10" class="wpcf7-form-control wpcf7-textarea form-control" aria-invalid="false"></textarea></span><br />
                <span class="wpcf7-form-control-wrap hello-wrap" style="display:none !important;visibility:hidden !important;"><input class="wpcf7-form-control wpcf7-text"  type="text" name="hello" value="" size="40" tabindex="-1" /><br><small>Please leave this field empty.</small></span>
            </div>
        </div>
        <div class="field_wrapper">
            <p class="title">How did you find us? <span class="optional">(optional)</span></p>
            <div class="field">
                <span class="wpcf7-form-control-wrap find-us"><input type="text" name="find-us" value="" size="40" class="wpcf7-form-control wpcf7-text form-control" aria-invalid="false" /></span>
            </div>
        </div>
        <div class="field_wrapper subscribe">
            <div class="field">
                <div class="td">
                    <span class="wpcf7-form-control-wrap newsletter"><span class="wpcf7-form-control wpcf7-checkbox" id="newsletter"><span class="wpcf7-list-item first last"><input type="checkbox" name="newsletter[]" value="yes" />&nbsp;<span class="wpcf7-list-item-label">yes</span></span></span></span>
                </div>
                <div class="td">
                    <label for="newsletter">I would like to receive newsletters from time to time.</label>
                </div>
                </p>
            </div>
        </div>
        <div class="field_wrapper submit">
            <div class="field">
                <input type="submit" value="Send" class="wpcf7-form-control wpcf7-submit btn" />
            </div>
        </div>
        <div class="wpcf7-response-output wpcf7-display-none"></div>
    </form>
</div>
3

There are 3 answers

10
rnevius On BEST ANSWER

Possibly the easiest way to achieve this is to enqueue your scripts after Contact Form 7's (via functions.php or your custom plugin), add a new function and bind it to DOMSubtreeModified, and check the form for errors.

When validation fails, Contact Form 7's AJAX function adds a span element with a class of wpcf7-not-valid-tip (as seen in the source).

You can target this for your specific field, by doing something similar to the following:

Example JS:

(function($){
    $('div.wpcf7 > form').submit(function(){
        // The name of a single field you're interested in targeting 
        var fieldName = 'some-field-name';

        $(this).find('span.' + fieldName).bind('DOMSubtreeModified', function(event) {
            // If an error has been appended to this input's parent span, do something
            if ( $(this).children('.wpcf7-not-valid-tip').length ) {
                // RUN YOUR FUNCTION HERE

                // Prevent this function from running multiple times
                $(this).off(event);
            }
        });
    });
})(jQuery);

Enqueue your scripts with, wpcf7_enqueue_scripts, to enqueue them after the default Contact Form 7 scripts (your path will likely be different):

/**
 * Enqueue Scripts with CF7 Dependencies
 */
function so30727367_enqueue_scripts() {
    wp_enqueue_script( 'stackoverflow-scripts', plugin_dir_url(__FILE__) . 'scripts.js', array('jquery'), null, true );
}
add_action( 'wpcf7_enqueue_scripts', 'so30727367_enqueue_scripts' );
2
SilentTremor On

you can make use of form submition event:

//attach handler on form submit
var formID = "myForm";
$('form#' + formID).submit(catchSubmit);

then you will need stop form submission and you will post it yourself, file upload case as well included in this hook, as well response from server can be catch in JavaScript and handled:

//custom handler for form submit
                    function catchSubmit(event) {
                        var uploadFileType = $('form#' + formID).attr('enctype') != undefined ? $('form#' + formID).attr('enctype').indexOf('multipart/form-data') != -1 ? true : false : false; //test if form has upload file functionality
                        event.preventDefault(); //stop html form post
                        if (uploadFileType) {
                            //ajax call for model + file upload
                            $.ajax({
                                url: $(this).attr("action"),
                                type: 'POST',
                                data: new FormData(this),
                                success: postSuccessHandler,
                                processData: false,
                                contentType: false
                            });
                            return;
                        }
                        else {
                            // ajax call for simple model/inputs
                            $.post($(this).attr("action"),
                               $(this).serialize(),
                               postSuccessHandler
                               );
                        }
                    }

and a post success handler where you can interpret your response for server:

function postSuccessHandler(data) {
//do something with returned html, json whatever
}
1
Jorgeuos On

Here's some code to get you started:

$(function () {
    // Optional nice scroll function
    function scrollTop(myTop){
        var myTop = (typeof myTop==='undefined'||myTop === null) ? 150 : myTop;
        $("html, body").animate({
        scrollTop: myTop
        }, 300);
    }
    $('.wpcf7-form').submit(function(event){
        var valid = true;
        $('[aria-required]').each(function(i,ele){
            if(ele.value == ''){
                $(this).parent().parent().addClass('alert');
                console.log('Required field empty: '+ ele.name);
                valid = false;
            }
        });

        // Handle additional validation here, set valid too false if it does not pass

        if (!valid){
            event.preventDefault();
            scrollTop();
            return false;
        }
        return true;
    });
});

EDIT:

Or the on_sent_ok: "doFunction();" Link

Or you could just see if the form has an error on page load:

$(function () {
    function checkErrors(){
        var invalid = $('.wpcf7-form').hasClass('invalid');
        var error = $('.wpcf7-form').hasClass('error');
        if (!invalid && !error) {
            return true;
        }
        return false;
    }
    checkErrors();
});