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

12,632

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' );
Share:
12,632
Brett
Author by

Brett

Updated on August 02, 2022

Comments

  • Brett
    Brett almost 2 years

    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>
    
  • Brett
    Brett almost 9 years
    But the thing is I only want to run the code if there is an error, so I don't want to stop the form from submitting (it is ajax based so no page reloads); I simply want it to run after the form submit, at which time I can check for the specified error and then do the required actions.
  • SilentTremor
    SilentTremor almost 9 years
    Exactly, your page isn't loading, you are submitting the form via ajax and interpret the response of server query over returned html as string, without reloading the page you can do this. Anyhow you could try searching for something, but with this you can do flowing things: submit the form (no page refresh), catch response search for error (html based like), if error found point out the problem.
  • Brett
    Brett almost 9 years
    Thanks. I will give that a shot and see how I go.
  • Brett
    Brett almost 9 years
    Ok, just tested this out. However one weird thing I noticed was that when I used an alert function to test if it worked, it seemed like it was in an infinite loop or something as the alert kept coming up over and over after I clicked ok.
  • Brett
    Brett almost 9 years
    Ok, just tested it out with console.log('Success!') and it output the term 125 times for some reason haha
  • rnevius
    rnevius almost 9 years
    Ah, I see what's happening. The function is returning the alert() each time the DOM tree is modified (which is a lot of times in this case). Give me a sec to update the function.
  • Brett
    Brett almost 9 years
    Ahhh thought that may be it haha
  • rnevius
    rnevius almost 9 years
    @Brett, I've updated the JS to prevent the issue you're experiencing.
  • rnevius
    rnevius almost 9 years
    on_sent_ok won't work, as nothing will be sent if there are validation errors
  • Brett
    Brett almost 9 years
    Hmmm... I'm trying to show/hide a field depending on if there is an error on that field, the showing of the error is working fine, however I cannot seem to get the field to go away once it shows even if there is no error on that field after resubmission. Any ideas on this?
  • rnevius
    rnevius almost 9 years
    Make sure you're re-hiding it, right at the beginning of the submit() function?
  • Brett
    Brett almost 9 years
    Yep, that's what I did, but it won't go away.
  • rnevius
    rnevius almost 9 years
  • Mostafa
    Mostafa about 7 years
    How get some filed value and use it on Additional Settings Tab of Form?