ajax user suggest

intermediate ajax, css, js, mysql, php, jquery, knockout 343 misterhaan

it’s been a few years since my ajax suggest guide, and since i’ve rewritten my ajax user suggestion code i figured an updated guide is in order. this guide covers using ajax with jquery and knockout to suggest users when typing in a text input field and support selection with the keyboard or mouse. familiarity with php, mysql, javascript, jquery, knockout, html, and css will make this guide more useful. specific css examples are not given since the best look will depend on the website using it. differences from the previous guide are including jquery and knockout, showing avatar and friend status with suggested usernames, and a single mysql query instead of two that get combined in php.

  1. find matching users
  2. define a view model
  3. create the search field
  4. support mouse selection
  5. support keyboard selection
  6. all 5 pages

define a view model

now that the server’s ready to build a list of users to suggest, i need a place to put that list on the client. it’s mostly going to mirror how it was on the server, but the suggested users will be in an observable array in knockout. when something is set up as observable, knockout can automatically update html when the value changes. it will even show every item in an array, which is perfect considering that’s how i get the users from the server.

in addition to the array of suggested users i also want the value of the user lookup field, a highlighted user pointer, and a selected user. i don’t always use the selected user but it’ll help keep this example contained. here’s how that looks inside a javascript class which is also applied to the page:

$(function() {
  ko.applyBindings(window.ViewModel = new UserSuggestViewModel());
});

function UserSuggestViewModel() {
  var self = this;
  self.usermatch = ko.observable("");
  self.users = ko.observableArray([]);
  self.cursor = ko.observable(false);
  self.selectedUser = ko.observable(false);
}

now it’s possible to ask the server for matching users and then fit them into the view model. that should happen when the usermatch observable updates. not every time it updates though; just when it’s at least three characters and it hasn’t changed in a short amount of time. the short amount of time i set to 250 milliseconds and used a javascript timeout to handle the wait. if the value changes before the time is up, cancel it and start the timer again.

subscribe to the usermatch observable with a function that makes an ajax call to get the list and then stores it in the observable array. the subscribe function runs every time the subscribed observable changes.

function UserSuggestViewModel() {
  var self = this;
  // ...
  self.usermatch.subscribe(function() {
    if(window.waitUserSuggest)
      clearTimeout(window.waitUserSuggest);
    window.waitUserSuggest = false;
    if(self.usermatch().length < 3)
      self.matchingusers([]);
    else {
      window.waitUserSuggest = setTimeout(function() {
        self.findingusers(true);
        $.get("/user/", {ajax: "suggest", match: self.usermatch()}, function(data, status, xhr) {
          var result = $.parseJSON(xhr.responseText);
          if(!result.fail) {
            self.users([]);
            for(var u = 0; u < result.users.length; u++)
              self.matchingusers.push(result.users[u]);
          } else
            alert(result.message);
          self.findingusers(false);
        });
      }, 250);
    }
  });
}

the function starts with clearing the previous timer if it was still waiting. then if there are less than 3 characters it clears any previous search results. if there are 3 or more characters it sets a timeout for 250 milliseconds (the 250 after the function definition) to actually request user search results.

to pass the value of the knockout observable usermatch through ajax, call it as a function with no arguments. i’m using jquery to simplify the ajax get request and safely parse the json response into a javascript object. after that it’s copying the users from the result array into the view model’s observable array. at this point there’s no way to set the search value or see the results in the view model, so on to the next step.

  1. find matching users
  2. define a view model
  3. create the search field
  4. support mouse selection
  5. support keyboard selection
  6. all 5 pages

how was it?

comments

there are no comments on this guide so far. you could be the first!

*