This video tutorial walks you through the process of using ajax in the WordPress admin within your own plugins. The end result of this tutorial is not a complete plugin, but it does show the entire process, step by step, of how ajax is utilized in the WordPress dashboard.

Unlike most of my tutorials, I do not use any pre-existing plugin or code as reference during the video; it is all coded live during the video, so mistakes and small bugs are common, but they really help to illustrate issues that developers often encounter while working with ajax.

The complete source code for this tutorial is free to download below if you are logged in.

[download id=”46″ format=”1″]

  1. paul

    thanks Pippin, that was really helpful!

    Have you tried Netbeans or PhpStorm IDE? Curious about why you are using Bluefish.
    Also, do you use xdebug? I find it really helpful to live debug.

    • Pippin

      Yep, hated them both. I personally really like Bluefish, and other super light weight non-IDE editors. My favorite editor of all time is Notepad++, but it doesn’t run on Linux.

    • poifox

      Excellent tut! πŸ™‚

      Eclipse + Aptana 3 is awesome for PHP dev, super fast and the code completion is super powerful. Saves me tons of time writing core PHP functions and any other function from WP or the framework I’m working with (when you include the wp-* in the build path of the project).

    • poifox

      Also when setup correctly, and you may want to know what the function does exactly you just position the caret on the function and hit F3 and Eclipse opens the function declaration, whereever it may be located inside WP πŸ™‚

    • Pippin

      I tried to use Eclipse/Aptana for a few days and couldn’t get comfortable with it. It just didn’t seem to work well for me.

    • Jun Pratama

      Same here, I like notepad++. And you can use it with Linux as well. It will run perfectly with “wine” program.

  2. riskiii

    You might try sublime text 2. It runs on linux.

  3. joacim

    Yeay! Could you do more stuff with this? like those checkboxes you’ve talked about at the end πŸ™‚ would be great.

    • Pippin

      I will try πŸ™‚

    • joacim

      Sweet πŸ˜€

  4. Patrick Miravalle

    I have been wanting to learn more about using AJAX with WordPress for a while now, and this tutorial has definitely given me a great foundation to work off of and to learn from. Thanks Pippin!

  5. 69developer

    I think there may be an error in the code where your doing nonce verification. You mentioned in the video you forget the proper setup of the wp_verify_nonce and you look at the codex to make sure.

    In your video you have the $nonce and $action backwards, I think?

    • Pippin

      Yep, it’s very possible I did them backwards. The action should be first and the nonce second.

  6. M@rc

    Thank you for this introduction to using ajax with WordPress, one of the best I’ve seen on the subject. It was very helpful to me. I am running into an issue however. I successfully used this on a meta box that has an input for searching post titles. After submitting the search, results get placed in an empty div just like you showed in your tutorial. But I would like to add another ajax call after the first one has displayed the search results, which should fetch basic info from a post when you click a search result. The problem is when I click on one of the results, nothing happens, even though I verified that the ajax is working. It looks like the jquery is not responding to the click event I added to the post title. Actually I am doubtful jquery even sees the post title that was inserted into the DOM via ajax, preventing me from targeting the post title?

    Am I doing this the wrong way? Is there a preferred way of handling multiple ajax calls in succession I should be aware of?

  7. locusuk

    Pippin
    Thank you for a great video article. I am embarking on the use of Ajax in my plugins for the first time and found this very helpful.
    I do however hope you can help me with something that is probably very simple, but I have not yet been able to resolve.
    I have managed to recreate your example for the use of Ajax on the admin side, but I am looking to replicate the idea on the frontend.
    I have tried to look it up and found the information, but cant seem to get it to work.
    I have reproduced the form and button your created within a shortcode function for display on a page, and also localized the admin-ajax.php script with the following code.
    wp_localize_script('WP-Ajax', 'ttftajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
    I have also added the required nopriv within the add_action code.
    add_action ('wp_ajax_nopriv_TTET_Get_Front_Results', 'TTET_Process_Frontend_Ajax');
    The button works as expected, but the page refreshes. I have not been able to find out why. Looking up the problem I have found that the return false; statement at the end of the java script should prevent this, but for some reason it does not.
    Can you help at all?
    Thanks
    Colin

    • Pippin

      Hi Colin,

      Can you show me examples of your code?

  8. locusuk

    Pippin

    Thank for getting back to me.
    This first section is the plugin file (excluding plugin headers)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    
    //Load Ajax Scripts For Admin
     
    function TTET_Load_Ajax_Frontend_Scripts(){
     
    	wp_enqueue_script('TTET-Ajax-Frontend', plugin_dir_url(__FILE__) . 'js/TTET-Ajax-Front.js', array('jquery'));
    	wp_localize_script('TTET-Ajax-Admin', 'TTET_vars', array('TTET_nonce' => wp_create_nonce('TTET_nonce')));
    	wp_localize_script('WP-Ajax', 'ttftajax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
    	wp_enqueue_script( 'json-form' ); 
    }
     
    add_action('wp_enqueue_scripts', 'TTET_Load_Ajax_Frontend_Scripts');
     
     
    //Populate Frontend Page Content Through Shortcode
     
    function TTET_Ajax_Frontend_Content(){
    global $TTET_Ajax_Settings;
    	?>
     
    			220810 Ajax Demo
     
     
    				<img id="TTET_Ajax_Loading" src="" class="waiting" style="display:none;">
     
     
     
    	<?php
    }
     
    add_shortcode("TTET_Ajax_Front", "TTET_Ajax_Frontend_Content");
     
     
    // Process Ajax Request
     
    function TTET_Process_Frontend_Ajax(){
     
    	if( !isset( $_POST['TTET_nonce'] ) || !wp_verify_nonce($_POST['TTET_nonce'], 'TTET_nonce')){
    		echo 'Permision Check Failure'; die();}
     
    	$TTET_Results = get_posts(array('post_type' => 'page', 'posts_per_page' => 10));	
     
    	if ( $TTET_Results ) :
     
    		echo '';
     
    		foreach($TTET_Results as $TTET_Result) {
     
    		echo '' . get_the_title($TTET_Result->ID) . '';
     
    		}
     
    		echo '';
     
    	else :
     
    		echo 'No Results Found';
     
    	endif;
     
    	die();
     
    }
     
    add_action ('wp_ajax_nopriv_TTET_Get_Front_Results', 'TTET_Process_Frontend_Ajax');

    and the following is the JS file

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    jQuery(document).ready(function($){
    	$('#TTET-Ajax-Form').submit(function(){
     
    		$('#TTET_Ajax_Loading').show();
     
     
    		data = {
    			action: 'TTET_Get_Front_Results',
    			TTET_nonce: TTET_vars.TTET_nonce
    		};
     
    		$.post(ttftajax.ajaxurl, data, function (response) {
    			$('#TTET_Results').html(response);
    			$('#TTET_Ajax_Loading').hide();	
     
     
    		});
     
     
     
    		return false;
    	});
    });

    I hope you can help me find what is probably staring me in the face.
    Thanks
    Colin

    • Jonthan Acosta

      locusuk, you have to prevent default right after the event is passed to
      $(β€˜#TTET-Ajax-Form’).submit(function(){});

      like this:

      $(β€˜#TTET-Ajax-Form’).submit(function(e){
      e.preventDefault();
      });

      That will stop the browser from reloading the page but execute the ajax request on form submission.

    • Pippin

      What Jonathan said is correct.

  9. locusuk

    @Jonthan Acosta and Pippin

    Thank you for you help. That sorted my problem. I thought it would be something simple.
    My one question is though, how come preventDefault(); was not required in the admin based version as per the video article?
    Thanks
    Colin

    • poifox

      @locusuk I really don’t know, since your code seems pretty much the same as the tutorial’s. in my experience doing e.preventDefault(); first and doing all your logic afterwards is more reliable.

      Also using $.ajax({url:””,data:{},success:function(){},error:function(){}}) is also easier to debug although it could potentially make you write more code, but more debuggable.

  10. Omprakash

    Nice Tutorial Really that will help everyone for doing ajax in wordpress. But i think if you provide sample demo of the code then it will be better.

  11. ifarhan

    This plugin tutorial is really nice, easily show how we implement AJAX in our custom Plguin.
    Really Love this tutorial
    Thanks Pippins.

  12. Samrat Khan

    An extra plus (+) for Notepad++, so it becomes Notepad+++, i like Notepad ++

  13. Barry Laminack

    Is there anything else that should be done to run this on a submenu of a plugin? I did the tutorial and it worked fine as a stand alone plugin that is accessed via the settings area. But when I tried to do this in my custom plugin on a submenu page using the same exact code (with updated paths) all I get is 0 when I click the button.

    • Pippin

      No, it shouldn’t be any different.

  14. luckdragon

    I’m trying to create a popup window (using highslide) that updates the data on the screen via ajax.. I know how to update the datatables and all that via ajax (with some help from your tutorial), but I was wondering if you know which file I need to include into the external php for the highslide window (I don’t need all of the admin area layout, just the database and wp function/connections)

    thank you in advance

    • Pippin

      That shouldn’t be done in an external file. It’s generally a bad idea to manually include core WP files in order to gain access to WP functions.

    • luckdragon

      that’s why I’m asking for advice on how to do it πŸ™‚ I like the look/feel of the highslide window, but don’t know if in addition to the ajax stuff I can put into wp, if there is a “popup” definition that doesn’t display all of the template stuff (I want to keep the styling, but basically it will just be a form on a white background with no header or menu,etc…)

  15. Andy Hodges

    Thank you for the post it seems to have a long life.

    I am looking at the codex for the difference in treatment of the AJAX script file in admin and elsewhere and struggling to find it. Any pointers?

    While I am here why on earth does WordPress feel the need to append the version number to the script? Is this part of its own encoding? (ajax.js?ver=3.5.1[from rendered source code])

    and thanks for dealing with the replies to everyone most helpful.

  16. Rob

    Wonderful tutorial!

    Thank you so much – I’m new-ish to plugin dev and this was thoroughly enlightening. Please keep up the good work!

    R

  17. nerd jgua

    Hi, very nice tutorial!

    It’s working here.

    One thing I just can’t get to work: I want to add a text input and get this output as variable for my custom funtion. How I can get this?

    My form:

    function add_form( ) {

    // Build the element to indicate this post has been read
    ?>

    <input type="submit" name="teste-submit" id="teste_submit" class="button-primary" value=""/>
    <img src="" class="waiting" id="teste_loading" style="display:none;"/>

    <?php
    } // end add_form

    And the function to process data:

    function teste_process_ajax() {

    if( !isset( $_POST['teste_nonce'] ) || !wp_verify_nonce($_POST['teste_nonce'], 'teste-nonce') )
    die('Permissions check failed');

    //$downloads = get_posts(array('post_type' => 'Post', 'posts_per_page' => 5));
    $downloads = TMDbScraper_search_andList_film($_POST['filmeinput']); // HOW TO GET FILMEINPUT?
    if( $downloads ) :
    echo '';
    foreach($downloads as $download) {
    echo ' ' . $download[0] . ' - ' . __('View Download', 'teste') . '';
    }
    echo '';
    else :
    echo '' . __('No results found', 'teste') . '';
    endif;

    die();
    }
    add_action('wp_ajax_teste_get_results', 'teste_process_ajax');
    </code

  18. nerd jgua

    (sorry double post… but the code on last was not ok)…
    Hi, very nice tutorial!

    It’s working here.

    One thing I just can’t get to work: I want to add a text input and get this output as variable for my custom funtion. How I can get this?

    My form:

    function add_form( ) {

    // Build the element to indicate this post has been read
    ?>

    <input type="submit" name="teste-submit" id="teste_submit" class="button-primary" value="”/>
    <img src="” class=”waiting” id=”teste_loading” style=”display:none;”/>

    ‘Post’, ‘posts_per_page’ => 5));
    $downloads = TMDbScraper_search_andList_film($_POST[‘filmeinput’]); // HOW TO GET FILMEINPUT?
    if( $downloads ) :
    echo ”;
    foreach($downloads as $download) {
    echo ‘ ‘ . $download[0] . ‘ – ‘ . __(‘View Download’, ‘teste’) . ‘‘;
    }
    echo ”;
    else :
    echo ” . __(‘No results found’, ‘teste’) . ”;
    endif;

    die();
    }
    add_action(‘wp_ajax_teste_get_results’, ‘teste_process_ajax’);

  19. nerd jgua

    (What a noob am I… 3rd try)…


    testing code...

    • Pippin

      Post your code to snippi.com then share the link.

  20. Fabrice SEVERIN

    Hi Pippin I’m so relieved I found this video because I had NOT understood that the action was compulsory in the post data, and that it is THE NAME OF THE ACTION which connects to the php handler. Yeahhhhh! thanks to you I can now manage ajax very easily in my plugin without desperately trying to use an external php file.

    To make it clear for a newbie the important point I mean is this:

    // if in php I do:

    add_action(‘wp_ajax_NAME_OF_MY_ACTION’, ‘my_action_callback’);
    function my_action_callback(){ … do sthg with the POST }

    // …then NAME_OF_MY_ACTION must match in javascript side:

    var data= “action=NAME_OF_MY_ACTION&data1=”+value1… ( or in array style )
    $.post(ajax_object.ajax_url, data, function(server_response)
    { // do sthg with server_response });

    Alleluia, Eureka! πŸ™‚ It’s just GREAT!

    • Pippin

      Glad to help!

    • Pippin

      Either of those should be fine.

  21. Ryan McNeil

    Hey, Pippin. Thanks for this tutorial!

    I was wondering what you could tell me about getting a php variable in the “process_ajax” function. I am trying to create a plugin where all images attached to a post are shown and when the “Remove” button is clicked, the attachment parent is set to 0. I was able to set up the ajax following your tutorial and I have the images in a metabox with a “Remove” button below. But the problem is, I’m not sure how to let the script know which image each button is connected to.

    Here’s the php:

    http://snippi.com/s/ggqe5q5

    and my javascript:

    http://snippi.com/s/4ody2zw

    I’m just not sure what to put in my process_ajax function to get the server to recognize the id of the image for the button clicked!

    If you could point me in direction of how to accomplish this, that would be great…maybe you already have a tutorial that would cover this type of thing?

    Thanks!

    Ryan

    • Pippin

      Any variable that you add to the data object in your JS (line 6) will be available in the PHP via the $_POST super global. For example, data currently has an “action” property. You can access this property in your PHP with $_POST[‘action’]

      Does that make sense?

    • poifox

      Also, you shouldn’t forget to sanitize that data is you are going to access the database based on the values you receive. in_array(needle, haystack); and other such validations will ensure you are only using the parameters you want with legal values, else you’re exposing your site to get hacked.

    • Pippin

      +1000 to that. Never insert unsanitized data into the database.

  22. poifox

    * sanitize that data IF you are going to access the database […]

  23. Mike Jordan

    This was posted well over a year ago and it’s still awesome. You rock Pippin.

  24. Farzad Karimnijad

    Dear Pippin,
    I have function in my wordpress plugins and the work fine in non-ajax mode. But when I use this function in ajax mode dont work correctly. (function execute but with incorrect result.)
    I think Cause of this incorrect result is that I use input text and get value of this textbox and sent to function and on the other I dont add anything to js file. how I do this?
    ——
    function aad_process_ajax() {
    $result = getlogin($_POST[“username”],$_POST[“password”]);
    if ($result != ‘loginfailure’)
    echo ‘ Login Successfull. ‘;
    else
    echo ‘ Login Failure. ‘;
    die();
    }

    Thankyou.

    • Pippin

      I’m sorry but I don’t really understand your question. Could you elaborate?

  25. Jack Lee

    function aad_style(){

    $output=’#adminmenu #toplevel_page_admin-ajax-demo .wp-menu-image:before {content: “\f321”;}’;

    echo $output;
    }

    add_action(‘admin_head’,’aad_style’);

    • Jack Lee

      <style>
      ….
      </style>
      was lost?

  26. Josh Fridey

    Hi Pippin,

    Great tutorials! I’ve been able to improve my plugins and theme development quite a bit after reading a lot of your tutorials.

    I’m running into a small issue ever since I added NONCE to my contact form ajax script. It seems to interfere with W3 Total Cache plugin.

    After filling out my contact form it returns a notification depending on success or error. It’s working just fine until I close the web browser and then it seems to be holding onto the NONCE Cache for some reason. If I clear out all cache in W3 Total Cache plugin and refresh the page, then it works again.

    You can visit my contact page at http://www.geekallday.com/contact

    And here’s the function that’s called back from ajax.

    function allVast_Contact_Form_Process_Ajax() {

    // User Posted Variables
    $name = $_POST[‘message_name’];
    $email = $_POST[‘message_email’];
    $message = $_POST[‘message_text’];
    $human = $_POST[‘message_human’];
    $submitted = $_POST[‘message_submitted’];

    // Response Messages
    $not_human = “Either you’re a spam bot, or you’ve been in front of the computer too long! πŸ™‚ If you’re human, please try again and complete the human verification.”;
    $prove_human = “We’re sorry but you must prove that you’re not a spam bot by answering a simple Math equation. I know it seems silly, but you’re doing us a huge favour!”;
    $missing_content = “You seem to have left out some required form fields. Please make sure you’ve filled out the Name, Email and Message fields.”;
    $email_invalid = “Please double check your email address and make sure it is valid! Example: yourname@provider.com“;
    $message_unsent = “We’re sorry but there seems to have been a server error! Please try sending your message again!”;
    $message_sent = “Thank you for reaching out to us! Your message has been successfully sent and we’ll get back to you as soon as we can!”;
    $permissions = “Permissions not verified! Please contact the administrator!”;

    // PHP Mailer Variables
    $to = get_option(‘admin_email’);
    $subject = $name . ” sent a message from the ” . get_bloginfo( ‘name’ ) . ” Contact Page.”;
    $headers = ‘From: ‘. $email . “\r\n” . ‘Reply-To: ‘ . $email . “\r\n”;

    if( !isset( $_POST[‘message_nonce’] ) OR !wp_verify_nonce( $_POST[‘message_nonce’], ‘allVast_Contact_Form_Security’ ) ) :
    allVast_Contact_Form_Response( “error”, $permissions );
    die();
    else :
    if ( !$human == 0 ) :
    if ( $human != 5 ) :
    allVast_Contact_Form_Response(“error”, $not_human); // HUMAN VERIFICATION FAIL ERROR
    else :
    // VALIDATE EMAIL
    if ( !filter_var( $email, FILTER_VALIDATE_EMAIL ) ) :
    allVast_Contact_Form_Response( “error”, $email_invalid );
    else :
    // VALIDATE NAME & MESSAGE
    if ( empty( $name ) OR empty( $message ) ) :
    allVast_Contact_Form_Response( “error”, $missing_content );
    else :
    // SEND EMAIL
    $sent = wp_mail($to, $subject, strip_tags($message), $headers);
    if($sent) :
    allVast_Contact_Form_Response( “success”, $message_sent );
    else :
    allVast_Contact_Form_Response( “error”, $message_unsent );
    endif;
    endif;
    endif;
    endif;
    elseif ( $submitted ) :
    allVast_Contact_Form_Response( “error”, $prove_human );
    endif;
    endif;

    die();

    }

    Any ideas?

    • Josh Fridey

      Okay after a bit of research I actually figured this one out myself.
      It may not have been a cache issue, but I’m not quite sure if I still have caching issues as I haven’t re enabled my Cache plugin.

      The issue was that NONCE wasn’t working unless I was logged in to WordPress as a user.

      I had to add an additional add_action aside from the wp_ajax.

      Here are the add_actions under my function.

      add_action(‘wp_ajax_allVast_Contact_Form_Validate’, ‘allVast_Contact_Form_Process_Ajax’);
      add_action(‘wp_ajax_nopriv_allVast_Contact_Form_Validate’, ‘allVast_Contact_Form_Process_Ajax’);

      The wp_ajax_nopriv add_action allowed me to pass NONCE with out having a user logged in.

      After reading up about NONCE I gathered that you really shouldn’t pass AJAX through WordPress with out having a NONCE in place.

      If you have any input on a more proper way to do this please let me know! πŸ™‚

      Thanks again for the great tutorials!

  27. Terrance Woest

    I’m new to coding and am working on building my first plugin with WordPress. It is always a little tricky when you don’t know 100% the adjustments you have to make to work within WordPress. I was struggling for days trying to get my ajax to work right with the normal $.post(‘enter your url here’ etc… rather than using ajaxurl. And the wordpress codex was unable to properly explain the ajaxurl object very efficiently for a beginner like me.

    So in a nutshell… You solved my 3 days of issues with the first half of this video. Thanks you so much (:

    • Pippin

      Glad to hear it!

  28. Darren Ladner

    Pippin,

    Loved this tutorial and I came back for another drive by but I do not see the video. I am running Windows 8. I tried using Chrome and FireFox but both browsers do not display the video. Help please. I really wanted to watch the great tutorial again.

    Thanks,
    Darren

    • Pippin

      Sorry about that, it’s fixed now!