WordPress Example: How to update and refresh current value stored in an ACF field

The post displays hows to use WordPress Ajax functions to display a field's value; and automatically refresh the field every 5 seconds. This example also includes examples of how to send an Ajax post to update the field.

In this example, each click oft the 'submit' button will increase the numerical value stored in the ACF field by 1.

Note: All code for this example can be found in my GitHub repo: https://github.com/ryanfitton/wordpress-update-acf-field-via-ajax-example.

 

Prerequisites

  • Ensure you have WordPress installed. Tested from WordPress 5.3.2
  • Install ACF Pro (Pro required for custom options page)
  • Upload the ACF export file acf-export-2020-03-31.json into your ACF settings
  • Download these jQuery libaries: RSVP.min.js and js.cookie.min.js.
  • jQuery is also required, however this should already be included from WordPress.

 

Explanation of files

  • tmpl_page_ajax.php -- Page template
  • functions.php -- Functions for Ajax calls
  • ajax.js -- JS Ajax calls

 

Step 1 -- Create a new page template

Create a page template in your theme folder with the code below. Then setup a page within WP Admin using this new page template: 'Ajax counter update'.

Create a new file named tmpl_page_ajax.php

<?php 
    /**
     * Template Name: Ajax counter update
     *
     * This is a generic page template
     */
?>

<?php get_header(); ?>

    <!-- Message -->
    <div id="message_notice"></div>

    
    <!-- Ajax content -->
    <div id="ajax_content_wrapper">

        <!-- Display value -->
        <div id="counter">
            Current count: <span><?php echo esc_html( get_field('counter_val', 'options_counter') ); ?></span>
        </div>


        <!-- /*---------------------------------------------------------*/ -->


        <form method="POST">
            <input type="submit" name="submit" id="submit" value="Submit">
        </form>

    </div>


<?php get_footer(); ?>

 

Step 2 -- Add code to your functions.php file

You may already have a functions.php file in your theme, if so; do NOT overwrite this file.

Instead, copy and paste the code below, and paste to the bottom of your existing theme file.

<?php 
    /*************************
        This code goes the theme's functions.php file
     *************************/

     

    /***********************
        ACF Option Pages
    ***********************/
    if( function_exists('acf_add_options_page') ) {
        //AJAX Counter options ACF Page
        acf_add_options_sub_page(array(
            'page_title'    => 'Ajax counter options',
            'menu_title'    => 'Ajax counter options',
            'parent_slug'   => 'options-general.php',
            'post_id'       => 'options_counter'          //Required to have fields for each page seperate
        ));
    }



    /***********************
        Ajax Counter - Enqueue files
    ***********************/
    function enqueue_ajax_form_script() {
        /*Load the script*/
        wp_enqueue_script(
            'rsvp',                                                                 //Handle: rsvp
            get_template_directory_uri() . '/rsvp.min.js',                          //Load 'rsvp.min.js'
            array( 'jquery' )                                                       //Depends on jQuery
        );

        wp_enqueue_script(
            'ajax_counter',                                                         //Handle: ajax_counter
            get_stylesheet_directory_uri() . '/ajax.js',                            //Load 'ajax.js'
            array( 'rsvp' )                                                         //Depends on rsvp
        );

        wp_enqueue_script(
            'jquery_cookie',                                                        //Handle: jquery_cookie
            //'https://cdn.jsdelivr.net/npm/js-cookie@beta/dist/js.cookie.min.js',  //Load 'js.cookie.min.js'
            get_template_directory_uri() . '/js.cookie.min.js',
            array( 'jquery' )                                                       //Depends on jQuery
        );
        
        /*Localise the scripts*/
            //For default options set in ACF Options page
            wp_localize_script('ajax_counter', 'script_localise', array(    //Name in JS: 'script_localise'
                //Setup variables
                'cookie_name'       => 'test_cookie_ajax',
                'cookie_duration'   => '60',
                'content_wrapper'   => 'ajax_content_wrapper',
                'content_messages'  => 'message_notice',

                //Default
                'ajaxurl' => admin_url('admin-ajax.php'),
                'nonce' => wp_create_nonce("nonce"),

                //For Counter Increase
                'action_counter_increase' => 'counter_increase',         //Action in JS: 'wp_ajax_counter_increase', Function: 'ajax_counter_increase'

                //For Counter Current Value
                'action_counter_current' => 'counter_current',               //Action in JS: 'wp_ajax_counter_current', Function: 'ajax_counter_current'
            ));

    }
    add_action( 'wp_enqueue_scripts', 'enqueue_ajax_form_script' );



    /***********************
        Ajax Counter Increase - Update counter
    ***********************/
    function ajax_counter_increase() {
        
        /*
            Nonce Security check
        */
        if ( ! wp_verify_nonce( $_POST['nonce'], 'nonce' ) ) {
            wp_send_json_error();
        }


        //Get current field value
        $get_field_value = get_field('counter_val', 'options_counter');


        //If current field is found
        if ( $get_field_value != '' ) {

            //Increase the value by 1
            $increase_value = 1;


            //New value
            $new_value = $get_field_value + $increase_value;

            //Update post meta value with new value
            if ( update_field( 'counter_val', $new_value, 'options_counter') ) {

                //Data to return via JSON
                $success = array(
                    'value' =>  esc_html( $new_value ),
                );

            } else {
                $error = array( 'value' => "Value could not be updated" );   
            }

        } else {
            $error = array( 'value' => "Cannot retrieve value" );    
        }


        /*
            Return Data
        */
        //If Error
        if ( !empty($error) ) {
            wp_send_json_error($error);
        
        //If success
        } elseif ( !empty($success) ) {
            wp_send_json_success( $success );
        
        //Catch all
        } else {
            wp_send_json_error();
        }


        die();
    }
    //Action: 'counter_increase' posted in AJAX, runs this function: 'ajax_counter_increase'
    add_action('wp_ajax_counter_increase', 'ajax_counter_increase');        //Run for Admin users
    add_action('wp_ajax_nopriv_counter_increase', 'ajax_counter_increase'); //Run for Non-Admin users



    /***********************
        Ajax Counter Current Value - get current counter value
    ***********************/
    function ajax_counter_current() {
        
        /*
            Nonce Security check
        */
        if ( ! wp_verify_nonce( $_POST['nonce'], 'nonce' ) ) {
            wp_send_json_error();
        }


        //Get current field value
        $get_field_value = get_field('counter_val', 'options_counter');


        //If current field is found
        if ( $get_field_value != '' ) {

            //Data to return via JSON
            $success = array(
                'value' => esc_html( $get_field_value ),
            );

        } else {
            $error = array( 'value' => "Cannot retrieve value" );
        }


        /*
            Return Data
        */
        //If Error
        if ( !empty($error) ) {
            wp_send_json_error($error);

        //If success
        } elseif ( !empty($success) ) {
            wp_send_json_success( $success );

        //Catch all
        } else {
            wp_send_json_error();
        }


        die();
    }
    //Action: 'counter_current' posted in AJAX, runs this function: 'ajax_counter_current'
    add_action('wp_ajax_counter_current', 'ajax_counter_current');          //Run for Admin users
    add_action('wp_ajax_nopriv_counter_current', 'ajax_counter_current');   //Run for Non-Admin users
?>

 

Step 3 -- Create JS file to hold AJAX calls

This file will hold all Ajax function calls. These function calls will communicate with the PHP functions within functions.php

Create a new file named ajax.js

jQuery(function ($) {

    //Promise polyfill
    //var RSVP = require('rsvp');   //Using the RSVP library for Promise functions in IE11: https://github.com/tildeio/rsvp.js/ and https://developers.google.com/web/fundamentals/primers/promises

    //Globals
    var increase_amount = false;


    // JS
    window.Counter = {

        /**
         * init - Runs first
         *
         */
        init: function () {

            this.cookie = script_localise.cookie_name;                          //The name of the cookie to be set/checked
            this.cookie_duration = parseInt(script_localise.cookie_duration);   //The duration of the cookie

            this.content_wrapper = jQuery("#" + script_localise.content_wrapper);
            this.content_messages = jQuery("#" + script_localise.content_messages);


            /* Disable standard form submissions on form submit button */
            this.content_wrapper.find('form').submit(function (event) {
                event.preventDefault();
            });


            /* Debugging */
            Cookies.remove(this.cookie);


            /* Run functions dependant on Cookie */
            cookie = Cookies.get(this.cookie);

            //If no cookie is set, continue displaying the interactive elements
            if (typeof cookie === 'undefined') {

                //Every 5 seconds, execute 'ajax_counter_current' function
                window.setInterval(function () {
                    Counter.ajax_counter_current();
                }, 5000);

                //Run once
                Counter.form_submission();


            //Else, cookie is set. Display message stating no form submissions can be made
            } else {

                //Set error message
                Counter.status_message('alert-error', 'You have already submitted the form.', this.content_messages);

                //Hide the content wrapper
                this.content_wrapper.hide();

            }

        },



        /* AJAX functions ---------------------------------------------------- */

        /**
         * ajax_counter_increase
         * Increase the counter via AJAX
         * =====================================================================
         */
        ajax_counter_increase: function (increase_value) {

            /* Create Variables */
            var increase_value = increase_value;

            if (increase_value < 1) {
                increase_value = false;
            }

            /* Run AJAX via Promise - https://www.taniarascia.com/how-to-promisify-an-ajax-call/ */
            return new RSVP.Promise(function (resolve, reject) {
                jQuery.ajax({
                    type: "POST",
                    async: true,
                    url: script_localise.ajaxurl,           //URL from functions.php
                    data: {
                        action: script_localise.action_counter_increase,        //Action name
                        increase_value: increase_value,
                        nonce: script_localise.nonce
                    },

                    //On success
                    success: function (data) {

                        //Set data to repsonse variable
                        response = data;

                        resolve(data)
                        //resolve(data.data['value'])

                        //console.log(data.data['value']);
                        //return data.data['value'];
                        console.log("done");
                    },

                    //On error
                    error: function (xhr, status) {
                        //console.log("'ajax_counter_increase' error.");
                        reject("'ajax_counter_increase' error.")
                    },

                    //On completion of AJAX call
                    complete: function (xhr, status) {
                        //console.log("'ajax_counter_increase' complete.");
                    }
                });
            });

        },



        /**
         * ajax_counter_current
         * Retrieve the current value of the counter via AJAX
         * =====================================================================
         */
        ajax_counter_current: function () {

            /* Run AJAX */
            jQuery.ajax({
                type: "POST",
                url: script_localise.ajaxurl,                       //URL from functions.php
                data: {
                    action: script_localise.action_counter_current,                 //Action name
                    nonce: script_localise.nonce
                },

                //On success
                success: function (data) {
                    Counter.callback_refresh_counter_current_value(data);           //Run the update function to display current up-to-date value in HTML
                },

                //On error
                error: function (xhr, status) {
                    console.log("'ajax_counter_current' error.");
                },

                //On completion of AJAX call
                complete: function (xhr, status) {
                    //console.log("'ajax_counter_current' completed.");
                }
            });

        },



        /* Callbacks ---------------------------------------------------- */

        /**
         * callback_refresh_counter_current_value
         * Retrieve the current counter value and update HTML
         * =====================================================================
         */
        callback_refresh_counter_current_value: function (response) {

            //If success
            if (response.success === true) {
                //Update the HTML content of Div ID '#counter'
                $('#counter span').html(response.data['value']);

            //Else, failure
            } else if (response.success === false) {
                //console.log("failure");
            }

        },



        /* Page functions ---------------------------------------------------- */

        /**
         * statusMessages
         * The status messages to be displayed, either success or error
         *      type = either 'success' or 'error'
         *      text = the text to display
         *      element = in which element to display
         * =====================================================================
         */
        status_message: function (type, text, element) {
            var element = jQuery(element);

            element.html('<div class="alert ' + type + '">' + text + '</div>');
        },



        /**
         * form_submission
         * Submission of the form
         * =====================================================================
         */
        form_submission: function () {

            /* Create Variables */
            var cookie = this.cookie;   //Cookie to be set
            var cookie_duration = this.cookie_duration      //Cookie duration
            var content_wrapper = this.content_wrapper;     //The content wrapper
            var content_messages = this.content_messages;   //The content message


            /* On submission of form */
            content_wrapper.find('form').submit(function (event) {

                /* Reset the amount to increase */
                increase_amount = 0;


                /* Run AJAX call to increase the counter */
                Counter.ajax_counter_increase(increase_amount).then(function (value) {

                    //If success
                    if (response.success === true) {
                        //console.log("'ajax_counter_increase' complete.");

                        /* Get the lastest counter value - refresh */
                        Counter.ajax_counter_current();

                        /* Set cookie for completion of form */
                        Cookies.set(cookie, cookie, { expires: cookie_duration });

                        /* Set success message */
                        Counter.status_message('alert-success', 'Thankyou for submitting.' + answer_feedback, content_messages);

                        content_wrapper.find('form').trigger("reset");


                    //Else, failure
                    } else if (response.success === false) {
                        //console.log("'ajax_counter_increase' error.");

                        /* Set error message */
                        Counter.status_message('alert-error', 'Unable to submit.', content_messages);
                    }

                });

            });

        },

    }


    $(function () {
        Counter.init(); //Run init
    });

});

Discuss on X (Twitter)