skip to Main Content

In order tracking in WooCommerce, track results are displayed as a whole new page when submitting the tracking form. However, what I wanted to see are the results in AJAX.

Here is the form in woocommerce/templates/order/form-tracking.php:

<form action="<?php echo esc_url( get_permalink( $post->ID ) ); ?>" method="post" class="woocommerce-form woocommerce-form-track-order track_order">

    <p><?php esc_html_e( 'To track your order, please enter your Order ID and the email you used during checkout. You can find these in your receipt and confirmation email.', 'woocommerce' ); ?></p>

    <p class="form-row form-row-first"><label for="orderid"><?php esc_html_e( 'Order ID', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="orderid" id="orderid" value="<?php echo isset( $_REQUEST['orderid'] ) ? esc_attr( wp_unslash( $_REQUEST['orderid'] ) ) : ''; ?>" placeholder="<?php esc_attr_e( 'Found in your order confirmation email.', 'woocommerce' ); ?>" /></p><?php // @codingStandardsIgnoreLine ?>
    <p class="form-row form-row-last"><label for="order_email"><?php esc_html_e( 'Billing email', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="order_email" id="order_email" value="<?php echo isset( $_REQUEST['order_email'] ) ? esc_attr( wp_unslash( $_REQUEST['order_email'] ) ) : ''; ?>" placeholder="<?php esc_attr_e( 'Email you used during checkout.', 'woocommerce' ); ?>" /></p><?php // @codingStandardsIgnoreLine ?>
    <div class="clear"></div>

    <p class="form-row"><button type="submit" class="button" name="track" value="<?php esc_attr_e( 'Track', 'woocommerce' ); ?>"><?php esc_html_e( 'Track', 'woocommerce' ); ?></button></p>
    <?php wp_nonce_field( 'woocommerce-order_tracking', 'woocommerce-order-tracking-nonce' ); ?>

</form>

I tried adding this in the same file right after the closing form tag and within the script tag:

var formData = new FormData();
formData.append('from_ajax', '1');// append this to your form.

 $('.track_order').submit(function() { // catch the form's submit event
    $.ajax({ // create an AJAX call...
        data: formData, // get the form data
        type: $(this).attr('method'), // GET or POST
        url: $(this).attr('action'), // the file to call
        success: function(response) { // on success..
            $('.track-results').html(response); // update the DIV
        }
    });
    return false; // cancel original event to prevent form submitting
});

if(isset($_POST['from_ajax']){
     if($_POST['from_ajax'] == 1){
         // do not load header or footer , just load required view to display.
     }
}

I’ve found this jQuery from another question asked almost 5 years ago, but the jQuery doesn’t seem to make any change, the order track results still show as whole new page. I don’t know what else I should add or if anything is amiss. Should I add the jQuery in another file? Should I add more or make any more modifications in the jQuery?

Thank you all, I’m a total noob!

2

Answers


  1. A couple of things are wrong. One tip is to check out any errors in the browser console first. There should be some in there.

    First possible problem:

    Returning false in the submit() handler could work to prevent the form from submitting, but only when there are no errors. A better way (also allowing you to keep seeing the browser console log easily) would be to use event.preventDefault()

    $('.track_order').submit(function(event) { // <-- add event as argument here
        event.preventDefault(); // <-- better way to prevent form from submitting
        // Rest of your script code
    }
    

    Second possible problem:

    $ might not exist. In WordPress, you should probably use jQuery in this code instead of the $ shorthand (unless you define $). So first step would be to replace the $ by jQuery inside of the <script> tags.

    jQuery('.track_order').submit(function(event) { // <-- replace $ by jQuery
        event.preventDefault();
        jQuery.ajax({ // // <-- replace $ by jQuery
            data: formData,
            type: jQuery(this).attr('method'), // <-- replace $ by jQuery
            url: jQuery(this).attr('action'), // <-- replace $ by jQuery
            success: function(response) {
                jQuery('.track-results').html(response); // <-- replace $ by jQuery
            }
        });
    });
    

    Third possible problem:

    Make sure you actually have a HTML element with class ‘track-results’ somewhere so the data can be displayed after loading through AJAX.

    <div class="track-results"></div>
    

    Fourth possible problem:

    FormData does not work together with jQuery’s ajax() method like that, because jQuery wants to stringify that, but it shouldn’t do that when the data is supplied as a FormData object.

    Two possible solutions:

    Solution 1 – Set processData and contentType to false when doing the ajax() request

        jQuery.ajax({
            processData: false,
            contentType: false,
            // All the other fields
        });
    

    OR solution 2 – Simply use a plain JavaScript object instead of FormData

    var formData = {
        'from_ajax': '1'
    }
    

    instead of

    var formData = new FormData();
    formData.append('from_ajax', '1');
    

    Fifth possible problem:

    This last part of your script is PHP and should not be in the JS script tags:

    if(isset($_POST['from_ajax']){
         if($_POST['from_ajax'] == 1){
             // do not load header or footer , just load required view to display.
         }
    }
    

    Instead, it should be in the PHP file mentioned in the action attribute of the form.

    Some extra information:

    Don’t just go and edit core WordPress files either. You can probably do what you need to do using an AJAX action in WordPress. Although the documentation is not very beginner friendly in my opinion, here it is: https://developer.wordpress.org/plugins/javascript/ajax/

    This older entry in the WP Codex might actually explain the basics in a simpler way: https://codex.wordpress.org/AJAX_in_Plugins

    Full example:

    I’m loading WP core here by including wp/wp-load.php so I can use the WP functions, and I have set the action attribute to be the test file itself. Just so I can give you a complete example contained in one file.

    <?php
    include 'wp/wp-load.php';
    if (isset($_POST['from_ajax']) && $_POST['from_ajax'] == 1) {
        die('tada! here is the example response ...');
    }
    ?>
    
    <form action="test.php" method="post" class="woocommerce-form woocommerce-form-track-order track_order">
    
        <p><?php esc_html_e( 'To track your order, please enter your Order ID and the email you used during checkout. You can find these in your receipt and confirmation email.', 'woocommerce' ); ?></p>
    
        <p class="form-row form-row-first"><label for="orderid"><?php esc_html_e( 'Order ID', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="orderid" id="orderid" value="<?php echo isset( $_REQUEST['orderid'] ) ? esc_attr( wp_unslash( $_REQUEST['orderid'] ) ) : ''; ?>" placeholder="<?php esc_attr_e( 'Found in your order confirmation email.', 'woocommerce' ); ?>" /></p><?php // @codingStandardsIgnoreLine ?>
        <p class="form-row form-row-last"><label for="order_email"><?php esc_html_e( 'Billing email', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="order_email" id="order_email" value="<?php echo isset( $_REQUEST['order_email'] ) ? esc_attr( wp_unslash( $_REQUEST['order_email'] ) ) : ''; ?>" placeholder="<?php esc_attr_e( 'Email you used during checkout.', 'woocommerce' ); ?>" /></p><?php // @codingStandardsIgnoreLine ?>
        <div class="clear"></div>
    
        <p class="form-row"><button type="submit" class="button" name="track" value="<?php esc_attr_e( 'Track', 'woocommerce' ); ?>"><?php esc_html_e( 'Track', 'woocommerce' ); ?></button></p>
        <?php wp_nonce_field( 'woocommerce-order_tracking', 'woocommerce-order-tracking-nonce' ); ?>
    
    </form>
    
    <div class="track-results">result will be shown here</div>
    
    <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
    <script>
    var formData = new FormData();
    formData.append('from_ajax', '1');// append this to your form.
    
    jQuery('.track_order').submit(function(event) { // catch the form's submit event
        event.preventDefault(); // prevent form submit
        jQuery.ajax({ // create an AJAX call...
            data: formData, // get the form data
            processData: false,
            contentType: false,
            type: $(this).attr('method'), // GET or POST
            url: $(this).attr('action'), // the file to call
            success: function(response) { // on success..
                $('.track-results').html(response); // update the DIV
            }
        });
    });
    </script>
    

    I hope this helps you out!

    Login or Signup to reply.
  2. <form action="<?php echo esc_url( get_permalink( $post->ID ) ); ?>" method="post" class="woocommerce-form woocommerce-form-track-order track_order">
    
        <p><?php esc_html_e( 'To track your order, please enter your Order ID and the email you used during checkout. You can find these in your receipt and confirmation email.', 'woocommerce' ); ?></p>
    
        <p class="form-row form-row-first"><label for="orderid"><?php esc_html_e( 'Order ID', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="orderid" id="orderid" value="<?php echo isset( $_REQUEST['orderid'] ) ? esc_attr( wp_unslash( $_REQUEST['orderid'] ) ) : ''; ?>" placeholder="<?php esc_attr_e( 'Found in your order confirmation email.', 'woocommerce' ); ?>" /></p><?php // @codingStandardsIgnoreLine ?>
        <p class="form-row form-row-last"><label for="order_email"><?php esc_html_e( 'Billing email', 'woocommerce' ); ?></label> <input class="input-text" type="text" name="order_email" id="order_email" value="<?php echo isset( $_REQUEST['order_email'] ) ? esc_attr( wp_unslash( $_REQUEST['order_email'] ) ) : ''; ?>" placeholder="<?php esc_attr_e( 'Email you used during checkout.', 'woocommerce' ); ?>" /></p><?php // @codingStandardsIgnoreLine ?>
        <div class="clear"></div>
    
        <p class="form-row"><button type="submit" class="button" name="track" value="<?php esc_attr_e( 'Track', 'woocommerce' ); ?>"><?php esc_html_e( 'Track', 'woocommerce' ); ?></button></p>
        <?php wp_nonce_field( 'woocommerce-order_tracking', 'woocommerce-order-tracking-nonce' ); ?>
    
    </form>
    
    <script>
    jQuery('.track_order').submit(function(event) {
        event.preventDefault();
        var formData = new FormData(this);
        jQuery.ajax({
            data: formData,
            processData: false,
            contentType: false,
            type: jQuery(this).attr('method'),
            url: 'tracking.php',
            success: function(response) {
                var orderInfo = jQuery(response).find('.woocommerce').html();
                jQuery('.track_order').html(orderInfo); // update the DIV
            }
        });
    });
    </script>
    

    and this is the tracking.php

    $notes = $order->get_customer_order_notes();
    ?>
    
    <p class="order-info">
        <?php
        echo wp_kses_post(
            apply_filters(
                'woocommerce_order_tracking_status',
                sprintf(
                    /* translators: 1: order number 2: order date 3: order status */
                    __( 'Order #%1$s was placed on %2$s and is currently %3$s.', 'woocommerce' ),
                    '<mark class="order-number">' . $order->get_order_number() . '</mark>',
                    '<mark class="order-date">' . wc_format_datetime( $order->get_date_created() ) . '</mark>',
                    '<mark class="order-status">' . wc_get_order_status_name( $order->get_status() ) . '</mark>'
                )
            )
        );
        ?>
    </p>
    
    <?php if ( $notes ) : ?>
        <h2><?php esc_html_e( 'Order updates', 'woocommerce' ); ?></h2>
        <ol class="commentlist notes">
            <?php foreach ( $notes as $note ) : ?>
            <li class="comment note">
                <div class="comment_container">
                    <div class="comment-text">
                        <p class="meta"><?php echo date_i18n( esc_html__( 'l jS of F Y, h:ia', 'woocommerce' ), strtotime( $note->comment_date ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
                        <div class="description">
                            <?php echo wpautop( wptexturize( $note->comment_content ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                        </div>
                        <div class="clear"></div>
                    </div>
                    <div class="clear"></div>
                </div>
            </li>
            <?php endforeach; ?>
        </ol>
    <?php endif; ?>
    
    <?php do_action( 'woocommerce_view_order', $order->get_id() ); ?>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search