skip to Main Content

I have my autocomplete working fine if there is hard coded data being fed into it. My PHP is returning a JSON result. I’m not sure where I am going wrong.

HTML

<div class="form-group bgcolor">
  <label for="send_to">Direct to: </label><input type="text" name="send_to" id="send_to" class="form-control send_to typeahead" placeholder="Leave blank normally">
</div>

Jquery

        $('.typeahead').typeahead({
          source: {
              groupName: {
               ajax({
                url: 'scripts/order_messaging.php',
                method: 'POST',
                data: JSON.stringify({action: 'autocomplete_to_user', query:query}),
                contentType: 'application/json',
                dataType: 'json',
                success:function(data)
                {
                 result($.map(data, function(item){
                  return item;
                 }));
                }
              })
            },
         },
         debug: true
        });

PHP

//autocomplete user name for user_to
if ( $_POST['action'] == 'autocomplete_to_user' ) {
    $stmt = $pdo->prepare('select * from login where username like :query');
    $stmt->bindValue('query', '%'.$_POST['query'].'%');
    $stmt->execute();
    $result = array();
    while($user_name = $stmt->fetch(PDO::FETCH_OBJ)) {
        array_push($result, $user_name->username);
    }
    echo json_encode($result);
}

I think it’s this line in my jQuery: data: {action: 'autocomplete_to_user', query:query}, Maybe I have a syntax problem.

4

Answers


  1. Chosen as BEST ANSWER

    Well, after much trial and error I got an autocomplete working using jQuery .autocomplete.

    I don't know what I was doing wrong with the typeahead but the documentation was hard to understand (probably because of my limited experience with jQuery).

    To all those in the future that need some help with this; here is a tutorial I found that was helpful: jquery ui autocomplete tutorial

    Thank you to everyone


  2. As per jQuery Ajax Documentation, dataType: 'json' evaluates the response as JSON and returns a JavaScript object.

    You need to stringify your data by using JSON.stringify({action: 'autocomplete_to_user', query:query}) before you send it to PHP. Also, you need to add header Content-Type: 'application/json' that tells you PHP code that request data is JSON. You can do this by adding contentType: 'application/json' in your Ajax settings.

    Your final jQuery code would look like this:

    $('.typeahead').typeahead({
      source: function(query, result)
      {
       $.ajax({
        url: 'scripts/order_messaging.php',
        method: 'POST',
        data: JSON.stringify({action: 'autocomplete_to_user', query:query}),
        contentType: 'application/json',
        dataType: 'json',
        success:function(data)
        {
         result($.map(data, function(item){
          return item;
         }));
        }
      })
     }
    });
    

    Refer to jQuery Ajax Documentation for mode details.
    Hope this helps!

    EDIT:

    You need to update your PHP code to read JSON. Please refer to this link.
    Your PHP Code should look like this:

    <?php
        // Read the input stream
        $body = file_get_contents("php://input");
    
        // Decode the JSON object
        $object = json_decode($body, true);
        //autocomplete user name for user_to
        if ( $object ['action'] == 'autocomplete_to_user' ) {
            $stmt = $pdo->prepare('select * from login where username like :query');
            $stmt->bindValue('query', '%'.$object['query'].'%');
            $stmt->execute();
            $result = array();
            while($user_name = $stmt->fetch(PDO::FETCH_OBJ)) {
                array_push($result, $user_name->username);
            }
            echo json_encode($result);
        }
    ?>
    
    
    Login or Signup to reply.
  3. I’ve tested the library and you need to change two things in order to make it work.

    1) You need to restructure the source parameter. You were giving it an AJAX callback which is not supported. According to the documentation, it accepts an array or an object with settings, so AJAX needs to be defined like this:

    $('.typeahead').typeahead({
        source: {
            // source has an "ajax" property where you just need to place
            // the object with AJAX params (the one you'd normally place inside
            // an $.ajax() call)
            ajax: {
                url: 'scripts/order_messaging.php',
                method: 'POST',
                data: {
                    action: 'autocomplete_to_user',
                    query: query,
                },
                dataType: 'json',
                path: '',
            },
        },
    });
    

    The path property of the ajax object is key here. It tells the typeahead function where to look for the data that was returned by the AJAX action. Since you’re encoding a one-dimensional array of values, you need to set it to an empty string, meaning your data is in the root of the response.

    If you were to return, for example, an array like echo json_encode(['users' => $result]); then you’d have to set the path to 'users' (because that is the index in the response that holds your data).

    2) You have to follow a strict HTML structure in order to make it work:

    <div class="typeahead__container">
        <div class="typeahead__field">
            <div class="typeahead__query">
                <input class="js-typeahead" name="q" autocomplete="off">
            </div>
        </div>
    </div>
    

    If you leave out any of these elements, it doesn’t trigger the functionality. This HTML structure is one of the first things they mention in the documentation.

    Login or Signup to reply.
  4. In my humble opinion, the documentation has some errors. For instance, in the demos, specifically the example Country v2 states

    A POST request will be sent with data myKey: myValue

    when in actuality the request being sent in the example is GET, because it depends on the type key of the ajax object of the first source (country in this case), which is not set, thus defaulting to GET.

    So, that being said, you really should stick to the proposed HTML structure (at least start with it, then take away stuff you don’t want gradually as long as it’ll let you).

    HTML

    <form id="form-country_v2" name="form-country_v2">
        <div class="typeahead__container">
            <div class="typeahead__field">
                <div class="typeahead__query">
                    <input class="typeahead" name="country_v2[query]" placeholder="Search" autocomplete="off">
                </div>
                <div class="typeahead__button">
                     <button type="submit">
                         <i class="typeahead__search-icon"></i>
                     </button>
                </div>
            </div>
        </div>
    </form>
    

    JS

    $(document).ready(() => {
      $('.typeahead').typeahead({
        template: "{{display}} <small style='color:#999;'>{{group}}</small>",
        source: {
          users: { //might as well be 'willy wonka', it doesn't matter
            ajax: {
              type: "POST",
              url: "scripts/order_messaging.php",
    
              //this is not actually needed for the request to work (reach the server),
              //this is used to access said request's returned data, it all
              //depends on how you structure the response in the server,
              //check out the php part
              path: "data.users",
    
              data: {
                action: 'autocomplete_to_user',
                query: 'username'
              }
            }
          }
        },
        callback: {
          //this is just to help you show the response in the html
          onResult: function(node, query, result, resultCount) {
            if (query === "") return;
    
            var text = "";
    
            if (result.length > 0 && result.length < resultCount) {
              text = "Showing <strong>" + result.length + "</strong> of <strong>" + resultCount + '</strong> elements matching "' + query + '"';
            } else if (result.length > 0) {
              text = 'Showing <strong>' + result.length + '</strong> elements matching "' + query + '"';
            } else {
              text = 'No results matching "' + query + '"';
            }
            $('#result-container').html(text);
    
          },
          onInit: function(node) { //and this is just informational
            console.log('Typeahead Initiated on ', node, node.selector);
          }
        }
      });
    });
    

    order_messaging.php

    if ($_POST['action'] == 'autocomplete_to_user') {
        $stmt = $pdo->prepare('select * from login where username like :query');
        $stmt->bindValue('query', '%' . $_POST['query'] . '%');
        $stmt->execute();
        $result = array();
        while ($user_name = $stmt->fetch(PDO::FETCH_OBJ)) {
            array_push($result, $user_name->username);
        }
    
        echo json_encode(array(
            "status" => true,
            "error" => null,
    
            //here you use whatever structure you want to return the data in,
            //as long as the payload is an array ($result).
            //remember in the JS you are expecting 'data.users'?
            //this is where it's coming from
            "data" => array(
                "users" => $result,
            )
        ));
    } else
        echo json_encode(array(
            "status" => true,
            "error" => null,
            "data" => array(
                "users" => [],
            )
        ));
    

    HIH

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search