Viewed   96 times

I'm familiar with using ajax in the ordinary way with jQuery.
I've played around it for a while, but don't understand what Wordpress needs to get it to work...
What I have here is taken from some tutorial or article.
This is in functions.php (in a child theme):

// code to load jquery - working fine

// code to load javascript file - working fine

// ENABLE AJAX :
function add_ajax()
{
   wp_localize_script(
    'function',
    'ajax_script',
    array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
}

$dirName = get_stylesheet_directory();  // use this to get child theme dir
require_once ($dirName."/ajax.php");  

add_action("wp_ajax_nopriv_function1", "function1"); // function in ajax.php

add_action('template_redirect', 'add_ajax');  

The jQuery itself is loading and working fine.

I have tried some basic ajax like the following:

jQuery(document).ready(function($){
    $('a.link').click(function(){
        $.ajax({
              url:     ajax_script.ajaxurl,
              data:    ({action  : 'function1'}),
              success: function(data){
                     $('#result').html(data);
              }
        });
        return false;
    });
});   

Besides this, I don't know how I can test to see if it's even loaded correctly to begin with...

Any help here would be appreciated.

EDIT:
In firebug this error:

ReferenceError: ajax_script is not defined
       url:   ajax_script.ajaxurl,

 Answers

3

As per your request I have put this in an answer for you.

As Hieu Nguyen suggested in his answer, you can use the ajaxurl javascript variable to reference the admin-ajax.php file. However this variable is not declared on the frontend. It is simple to declare this on the front end, by putting the following in the header.php of your theme.

<script type="text/javascript">
    var ajaxurl = "<?php echo admin_url('admin-ajax.php'); ?>";
</script>

As is described in the Wordpress AJAX documentation, you have two different hooks - wp_ajax_(action), and wp_ajax_nopriv_(action). The difference between these is:

  • wp_ajax_(action): This is fired if the ajax call is made from inside the admin panel.
  • wp_ajax_nopriv_(action): This is fired if the ajax call is made from the front end of the website.

Everything else is described in the documentation linked above. Happy coding!

P.S. Here is an example that should work. (I have not tested)

Front end:

<script type="text/javascript">
    jQuery.ajax({
        url: ajaxurl,
        data: {
            action: 'my_action_name'
        },
        type: 'GET'
    });
</script>

Back end:

<?php
    function my_ajax_callback_function() {
        // Implement ajax function here
    }
    add_action( 'wp_ajax_my_action_name', 'my_ajax_callback_function' );    // If called from admin panel
    add_action( 'wp_ajax_nopriv_my_action_name', 'my_ajax_callback_function' );    // If called from front end
?>

UPDATE Even though this is an old answer, it seems to keep getting thumbs up from people - which is great! I think this may be of use to some people.

WordPress has a function wp_localize_script. This function takes an array of data as the third parameter, intended to be translations, like the following:

var translation = {
    success: "Success!",
    failure: "Failure!",
    error: "Error!",
    ...
};

So this simply loads an object into the HTML head tag. This can be utilized in the following way:

Backend:

wp_localize_script( 'FrontEndAjax', 'ajax', array(
    'url' => admin_url( 'admin-ajax.php' )
) );

The advantage of this method is that it may be used in both themes AND plugins, as you are not hard-coding the ajax URL variable into the theme.

On the front end, the URL is now accessible via ajax.url, rather than simply ajaxurl in the previous examples.

Thursday, December 8, 2022
4

In backend there is global ajaxurl variable defined by WordPress itself.

This variable is not created by WP in frontend. It means that if you want to use AJAX calls in frontend, then you have to define such variable by yourself.

Good way to do this is to use wp_localize_script.

Let's assume your AJAX calls are in my-ajax-script.js file, then add wp_localize_script for this JS file like so:

function my_enqueue() {
      wp_enqueue_script( 'ajax-script', get_template_directory_uri() . '/js/my-ajax-script.js', array('jquery') );
      wp_localize_script( 'ajax-script', 'my_ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
 }
 add_action( 'wp_enqueue_scripts', 'my_enqueue' );

After localizing your JS file, you can use my_ajax_object object in your JS file:

jQuery.ajax({
    type: "post",
    dataType: "json",
    url: my_ajax_object.ajax_url,
    data: formData,
    success: function(msg){
        console.log(msg);
    }
});
Sunday, September 11, 2022
4

You need to specify when the load should happen, try this.

<?php
/*
Plugin Name: Ava Test
Plugin URI: https://matsio.com
Description: A plugin that is used for my javascript tests
Author: Ronny Kibet
Author URI: https://matsio.com
version: 1.001
*/

add_action('wp_enqueue_scripts','ava_test_init');

function ava_test_init() {
    wp_enqueue_script( 'ava-test-js', plugins_url( '/js/ava_test_.js', __FILE__ ));
}

Also, there are errors in your JS, but I have seen the correct version in some answers, hope this helps

Update : There is a hook called wp_enqueue_scripts, as mentioned by @brasofilo which should be used in lieu of init for loading scripts.

Wednesday, October 26, 2022
 
antc
 
3

Ok, so first localize your ajaxurl object

add_action( 'wp_enqueue_scripts', 'frontend_enqueued_scripts' );

/**
 * Localization object
 *
 * @since 1.0.0
 */
function frontend_enqueued_scripts() {

    wp_enqueue_script( 'script', get_template_directory_uri() . '/js/custom.js', array( 'jquery' ), '', true );
    wp_localize_script( 'script', 'ajax_object', array(
        'ajaxurl' => admin_url( 'admin-ajax.php' ),
    ));
}

If you have, in your functions.php a place where you are enqueuing front end scripts place the wp_enqueue_script and wp_localize_script part in there. Also if you are placing your ajax calling javascript inside a file that is not called custom.js change the name to point to it. I always use custom.js as a file where I store all my theme related javascript.

The above code will create an ajax_object object on your front end that will be available to the code inside the custom.js, since you've attached it to that script. The handles in the enqueued file and localized script (in our case script) must be the same for this to work.

Then you can create, in functions.php file, or in any included file where you put your ajax functions, a callback function

/**
 * Front and back end ajax hooks.
 */
add_action( 'wp_ajax_edit_committee', 'edit_committee' );
add_action( 'wp_ajax_nopriv_edit_committee', 'edit_committee' );

/**
 * Ajax callback function
 *
 * @since 1.0.0
 */
function edit_committee() {
    global $wpdb;

    if ( isset( $_POST['id'], $_POST['committee_nonce'] ) && wp_verify_nonce( sanitize_key( $_POST['committee_nonce'] ), 'committee_nonce_action' ) && '' !== $_POST['id'] ) { // Input var okay.
        $id          = ( isset( $_POST['id'] ) && '' !== $_POST['id'] ) ? sanitize_text_field( wp_unslash( $_POST['id'] ) ); : ''; // Input var okay.
        $name        = ( isset( $_POST['name'] ) && '' !== $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ); : ''; // Input var okay.
        $created     = ( isset( $_POST['create_date'] ) && '' !== $_POST['create_date'] ) ? sanitize_text_field( wp_unslash( $_POST['create_date'] ) ); : ''; // Input var okay.
        $stats       = ( isset( $_POST['stats'] ) && '' !== $_POST['stats'] ) ? sanitize_text_field( wp_unslash( $_POST['stats'] ) ); : ''; // Input var okay.
        $date_expire = ( isset( $_POST['date_expire'] ) && '' !== $_POST['date_expire'] ) ? sanitize_text_field( wp_unslash( $_POST['date_expire'] ) ); : ''; // Input var okay.

        $updated = $wpdb->update( 'itemsTable', array(  'name' => $name ), array( 'committee_id' => $id ), array( '%s' ) );
        if( false !== $updated ) {
            wp_die( 'success' );
        } else {
            wp_die( 'fail' );
        }

    }
}

I added the sanitization checks. It's crucial that you include a nonce in your form that you'll use to submit the data.

You can add it by placing

wp_nonce_field( 'committee_nonce_action', 'committee_nonce' );

inside the <form> element on your front end. This will generate a nonce, which is a good security measure, especially when you're writing to the database.

The callback function will check if the nonce is set, if the $_POST['id'] variable is set and not empty, and will first verify the nonce.

Then you can carry on with the execution of the function.

I left all the $POST variables there even though you're not using them, but maybe you'll want to use them later on. I also sanitized them and unslashed them.

The // Input var okay. comment is for phpcs purposes, you can ignore that.

Then you preform the update. If you have the itemsTable in the database it should update it with the data you provided.

The last but not the least is the javascript code. I assumed that you are preforming the ajax call on some kind of button click. This needs to be changed for it to work (I used #update_button, you'll place the correct id or class of your button)

jQuery(document).ready(function($) {
    'use strict';

    $('#update_button').on('click', function(e){
        e.preventDefault();

        var ID = $(this).attr('id'); // Button that is clicked is in $(this) object
        var name = $('#name_input_'+ID).val();
        var create_date = $('#created_input_'+ID).val();
        var stats = $('#status_input_'+ID).val();
        var date_expire = $('#disbanded_input_'+ID).val();

        // Can place loading image here
        if ( name.length > 0 || create_date.length > 0 || stats.length > 0 || date_expire.length > 0 ) {
            $.ajax({
                type: 'POST',
                url: ajax_object.ajaxurl,
                data: {
                    'action' : 'edit_committee',
                    'id' : ID,
                    'name' : name,
                    'create_date' : create_date,
                    'stats' : stats,
                    'date_expire' : date_expire,
                    'committee_nonce' : $( '#committee_nonce' ).val()
                },
                cache: false,
                error: function( jqXHR, textStatus, errorThrown ) {
                    console.log( jqXHR + ' :: ' + textStatus + ' :: ' + errorThrown );
                },
                success: function (html) {
                    if ( html == 'success' ) {
                        $('#name_'+ID).html(name);
                        $('#createDate_'+ID).html(create_date);
                        $('#stats_'+ID).html(stats);
                        $('#dateExpire_'+ID).html(date_expire);
                    }
                }
            });
        } else {
            alert('Enter text to make an edit.');
        }

    });

});

I've also changed variable names to short_name format, instead of shortName. I find that neater.

Notice that for the url, we used ajax_object.ajaxurl - this is the localized ajax_object from the beginning, referencing to the correct path of the admin-ajax.php file. The data is just your string, but written as an object.

So when you click the button, your ajax call will put all your data in a global $_POST variable.

You can check it by having inspector running and clicking Network > XHR tab

Also if you're not sure what your $_POST variable holds, put

error_log(print_r($_POST, true));

in your edit_committee() function, right before the validation check (the if condition). If you have debugging enabled in your wp-config.php

define('WP_DEBUG', true);
ini_set('log_errors',TRUE);
ini_set('error_reporting', E_ALL);
ini_set('error_log', dirname(__FILE__) . '/error_log.txt');

You'll have error_log.txt in the root of your WordPress installation, and you can check what the contents of the $_POST variable is.

Hope this helps ;)

Saturday, October 8, 2022
 
4

serialize() will generate a form encoded string that looks like:

name=foo&email=foo@bar.com&age=86

If you pass an object to data jQuery will convert it to this format by default.

Mixing serialize and object thus gets tricky so is best to to stick to one method or the other.

Try this:

var data2 = jQuery('#newIdeaForm').serialize()
jQuery.ajax({
    type: 'POST',
    url: myAjax.ajaxurl,
    data: data2 + '&action=savedata',
    success: function() {
        .....

    }
});

Now you can access all the form name's using $_POST['fieldName']

Sunday, December 11, 2022
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :