|

jQuery Autocomplete As You Type

jQuery Autocomplete As You Type

This tutorial will add the feature of autocomplete as you type. In the form where a user can enter a reply to a thread, we want the application to automatically start fetching usernames to choose from when you type a string that begins with the @ symbol. There is a jQuery plugin built for this exact purpose called At.js. In addition to autocomplete of usernames, the plugin also offers emoji like characters such as smileys, coffee cups, and more. Since the reply form is actually a VueJS component, that means we’ll need to import the jQuery plugin into the component to make it work. Let’s tinker with At.js now.


Installing At.js

Before we can use the plugin, we’ll need to install it. We install at.js and jquery.caret using the yarn package manager here.

vagrant@homestead:~/Code/forumio$ yarn add at.js save 
vagrant@homestead:~/Code/forumio$ yarn add jquery.caret save

Import jQuery Plugin To Vue Component

In the component we want to make use of the At.js plugin, we’ll need to make use of an import statement. In the script area of the NewReply component, this is how to import those two modules.


Bootup The Watcher

Since we’re now working with Javascript we’ll need to boot up the watcher.

vagrant@homestead:~/Code/forumio$ yarn run watch-poll

Now as we update the files in question, webpack does it’s job in the background recompiling and minifying on the fly.


Leveraging At.js In Vue Component

Now that the code is available for use inside of the Vue component itself, we can add some markup to make use of the auto complete functionality. We have highlighted the markup in question here.

Let’s examine how this works. First off, we put this inside the mounted() VueJS function. This triggers after the Vue instance has been mounted, when the original target element is replaced with the Vue element.

Next, we use jQuery to target the element that we want to add autocomplete functionality to. Via $(‘#body’), we are targeting the element which has the id of ‘body’. Note that the <textarea> of this Vue component has an id of ‘body’ so this is what the at.js plugin works with.

After this, the atwho() method is called. This is the main function used in the at.js library. An object is passed to the call of atwho(). The ‘at’ property is where you specify a character to make the plugin take action. In our case, the @ symbol is used. The ‘delay’ property takes a value in milliseconds.

Next up is the ‘callbacks’ property and in here are functions set for handling and rendering the data. Inside the callbacks property is the call to remoteFilter which at.js uses to fetch matching data from the server to actually complete the auto suggest feature. In fact, if we load up a threads page and start typing into the text area, if we enter an @ symbol we can see ajax requests fire off to the server.
at mention at js autocomplete


Configure The Laravel API

The front end side of this is more or less in place. Now we need to set up an endpoint on the API so that it can respond to those ajax requests. What the endpoint will do is to search the database for potential matches to the typed text and return those potential matches to the front end. The front end then loops over the results and builds out a list of potential matches.


Adding a route

We can add this line of code to the end of the web.php routes file.


Add a test

Let’s add a test for this api endpoint.

  • Given we have a user LilKim
  • Given we have a user LilJim
  • Given we have a user JoeBlow
  • When a json request is made
  • Then we should have 2 possible matches

Running the test gives us a ReflectionException of “Class App\Http\Controllers\Api\UsersController does not exist”

vagrant@homestead:~/Code/forumio$ phpunit --filter test_it_can_fetch_all_mentioned_users_starting_with_the_given_characters
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 808 ms, Memory: 8.00MB

There was 1 error:

1) Tests\Feature\MentionUsersTest::test_it_can_fetch_all_mentioned_users_starting_with_the_given_characters
ReflectionException: Class App\Http\Controllers\Api\UsersController does not exist

That’s ok! All we need to do is build out a new controller. Here we go!

vagrant@homestead:~/Code/forumio$ php artisan make:controller Api/UsersController
Controller created successfully.

Note how we prefix the name of the controller with the string of ‘Api’. This automatically creates a new directory for our API controllers, and puts this new UsersController in the directory for us. Now that our class is created, we can run the test once more.

vagrant@homestead:~/Code/forumio$ phpunit --filter test_it_can_fetch_all_mentioned_users_starting_with_the_given_characters
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

E                                                                   1 / 1 (100%)

Time: 845 ms, Memory: 8.00MB

There was 1 error:

1) Tests\Feature\MentionUsersTest::test_it_can_fetch_all_mentioned_users_starting_with_the_given_characters
BadMethodCallException: Method [index] does not exist on [App\Http\Controllers\Api\UsersController].

It looks like we’re missing in index() method. Easy fix!

The index method does not yet do anything, but it should clear the prior error in the test and get us one step closer to green. We can run the test again to see what we need to do.

vagrant@homestead:~/Code/forumio$ phpunit --filter test_it_can_fetch_all_mentioned_users_starting_with_the_given_characters
PHPUnit 6.5.5 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 810 ms, Memory: 10.00MB

There was 1 failure:

1) Tests\Feature\MentionUsersTest::test_it_can_fetch_all_mentioned_users_starting_with_the_given_characters
Invalid JSON was returned from the route.

Ok, invalid json is returned. We can fix that. First off, what do we need this index() method to do? Well, it is going to make a database query. Specifically, it is going to query the User model, so we need to make use of that. Now, we will use a “where” clause using the passed in data from the front end. Once that is complete, we return the results as json. Here is what that should look like now.

With that, we see my favorite color. GREEN!
phpunit test now passing with GREEN

That means this should now work in the browser. If we try it, it kind of works. The potential matches are showing up, but not how we might expect!
kind of working


Adding At.js CSS

So the reason why things look funny so far, is that we have no styling to properly format the auto suggest results. We can fix that however by copying the css which comes with at.js to the public directory of our application. First we create the new directory within public/css, then we copy the contents over.

vagrant@homestead:~/Code/forumio$ mkdir public/css/vendor
vagrant@homestead:~/Code/forumio$ cp node_modules/at.js/dist/css/jquery.atwho.css ./public/css/vendor/

Selectively Referencing A Stylesheet

We now need to reference that stylesheet in order for the styling to take effect in the form. We don’t need this stylesheet anywhere else in the application however, so we should make use of it only when needed. This is actually fairly easy to do. In threads/show.blade.php we will add this markup.

Now in the main app.blade.php layout file, we can add the highlighted line.

This allows us to add the needed stylesheet on demand so to speak. And will you look at that?! Cool!
jquery autocomplete as you type working example


Linkify User Names

The last thing we can do in this tutorial is to make sure that the user names are linkified, or wrapped in an anchor tag when mentioning a user. In the Reply.php model, we can add a public function to set the body attribute like so. This just makes use of a handy regular expression to create a hyperlink for user profiles.

We’ll also need to make a small tweak in the Reply.vue component. Note that we now use v-html instead of v-text.

Now our usernames get linkified and we can click through to see their profiles.
turn user name into clickable link


jQuery Autocomplete As You Type Summary

We were able to get the auto suggest feature working in our application using the very useful at.js jQuery plugin. Once we added a small amount of markup to the front end, we had to set up an api on the backend to return the potential matches. In addition, we had to copy over some custom css in order to render the auto complete of user names so that they look slick in the browser.

|