0

Bit of background: I am building an autocompleting-search box for a list of Trades (a Custom Taxonomy). I asked this question and very helpfully got a much better understanding of how WordPress and AJAX work together (Thanks G.M)! However, he said that I should use wp_localize_script so that the PHP isn't accessible on the front-end. I knew about this function but had never used it so with a bit of reluctance I got stuck in.

I found this post which also had an incredibly useful explanation of how WordPress and AJAX work together. I implemented that code provided by Stephen Harris, but I've got an error in my console, whenever I search for anything in the search bar:

TypeError: '["Accountants","Electricians","Painters","Plumbers"]' is not a valid argument for 'in' (evaluating 'b-1 in a')

and here is my PHP code:

wp_enqueue_script("autocomplete", get_template_directory_uri() . '/assets/js/autocomplete.js', array( 'jquery', 'jquery-form', 'json2' ), false, true );
wp_localize_script("autocomplete", "MyAjax_object", array(
    'ajaxurl' => admin_url( 'admin-ajax.php' ),
    'myajax_nonce' => wp_create_nonce( 'myajax_nonce_val' ),
    'action' => 'myajax-submit'
));
function get_my_suggestions() {
    // This function should query the database and get results as an array of rows:
    // GET the recieved data: 'term' (what has been typed by the user)
    $term = $_GET['term'];
    $trades = get_terms( 'trade', array( 'fields' => 'names' ) );
    $tradesList = '["' . implode( '","', $trades ) . '"]';

    // echo JSON to page  and exit.
    $response = $_GET["callback"]."(". json_encode($tradesList) .")";  
    echo $response;  
    exit;
}
add_action( 'wp_ajax_myajax-submit', 'get_my_suggestions' );

and JavaScript:

$(document).ready(function() {
    $(".main-search-field").autocomplete({
    source: function( request, response ) {  
            jQuery.getJSON( MyAjax_object.ajaxurl + "?callback=?&action=myajax-submit", request, function( data ) {
                response( jQuery.map( data, function( item ) {
                    jQuery.each( item, function( i, val ) {
                        val.label = val.whatever; // build result for autocomplete from suggestion array data
                    } );
                    return item;
                } ) );
            } );  
        }, 
        minLength: 1,
        appendTo: ".search-container"
    }); 
});

Does anyone know why I get that error? The JavaScript loads fine - it adds in the markup for the suggestions list, but it's empty. Also, I've noticed that whenever I search for something in the input box, a class, ui-autocomplete-loading is added to the input box. Not sure if that's important but it might help someone out.

Thanks for any help :)

2 Answers 2

0

If you follow the second approach in the linked Q\A, you do not need ajax, but just to pass the array of terms to the script.

First of all in your functions.php (or equivalent) enqueue the script and pass the array of trades via wp_localize_script:

add_action( 'wp_enqueue_scripts', function() {

  /* you should check if the page is the one that include the form, you know how,
   * E.G.:
   *
   * if ( ! is_page( 'my-page-with-form' ) ) return;
   *
   */

  wp_enqueue_script(
    'my-theme-autocomplete', // is better to prefix everything in WP
    get_template_directory_uri() . '/assets/js/autocomplete.js',
    // put jquery-ui-autocomplete among dependencies
    array( 'jquery', 'jquery-form', 'json2', 'jquery-ui-autocomplete' ),
    NULL,
    true
  );

  wp_localize_script( 'my-theme-autocomplete', 'MyAjax_object', array(
    'all_trades' => implode( ',', get_terms( 'trade', array( 'fields' => 'names' ) ) )
  ) );

});

Now the autocomplete.js file should contain:

jQuery(document).ready( function($) {

  $( '.main-search-field' ).autocomplete({
    source: MyAjax_object.all_trades.split(','),
    minLength: 1
  });

});

Notes

  • It is important to check if the page is the one that contain form, because otherwise the scripts (jquery, jquery-form, json2, jquery-ui-autocomplete and your autocomplete.js) will be added on every page, and also get_terms will always be called, slowing down page loading, so be sure to use the script only if needed.

  • In code above the autocomplete.js contain only 5 lines of code, and don't worth to create an additional file only for that, if you have a javascript file you load on all pages (or that is loaded in the page where you need the autocomplete) put the code there, just be sure to adjust the handle (first argument) for wp_localize_script.

  • First code snippet uses an anonymous function (closure) so require PHP 5.3+.

1
  • Thanks so much! This is great. My form is being loaded in via a shortcode so I'll make sure I add in the code so it only loads the files when necessary. Thanks for all your help :)
    – Tom Oakley
    Commented Jul 16, 2014 at 15:38
0

You don't need to do this part $tradesList = '["' . implode( '","', $trades ) . '"]'; json_encode converts array to json.

EDIT:

php code

function get_my_suggestions() {
  // This function should query the database and get results as an array of rows:
  // GET the recieved data: 'term' (what has been typed by the user)
  $term = $_GET['term'];
  $trades = array('gadha', 'chagol', 'patha');
  //$tradesList = '["' . implode( '","', $trades ) . '"]';

  // echo JSON to page  and exit.
  $response = $_GET["callback"]."(". json_encode($trades) .")";
  echo $response;
  exit;
}
add_action( 'wp_ajax_myajax-submit', 'get_my_suggestions' );

javascript

$(document).ready(function() {
$(".main-search-field").autocomplete({
source: function( request, response ) {  
        jQuery.getJSON( MyAjax_object.ajaxurl + "?callback=?&action=myajax-submit", request, function( data ) {
            response( jQuery.map( data, function( item ) {
                jQuery.each( item, function( i, val ) {
                    val.label = val; // the generated array form get_terms do not have a key so pass val to label
                } );
                return item;
            } ) );
        } );  
    }, 
    minLength: 1,
    appendTo: ".search-container"
}); 

});

3
  • Ah, thanks, that was left over from the previous answer. I've removed that line and now I get this error: TypeError: 'null' is not an object (evaluating 'a.length').
    – Tom Oakley
    Commented Jul 16, 2014 at 13:40
  • You need to pass $trades to json_encode
    – sabarnix
    Commented Jul 16, 2014 at 14:42
  • Oh. Thanks. Fixed that but now we're back to the original error, TypeError: 'Accountants' is not a valid argument for 'in' (evaluating 'b-1 in a'). It seems to correspond to line 5 and 6, response( jQuery.map( data, function( item ) { jQuery.each( item, function( i, val ) {
    – Tom Oakley
    Commented Jul 16, 2014 at 14:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.