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 templatefunctions.php
-- Functions for Ajax callsajax.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
});
});