Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

WallyJ's avatar

Best Autocomplete for Laravel Projects with MySQL backend

I normally receive awesome help from these forums, but in the Javascript category I posted a question here about Typeahead.js and have received no replies:

https://laracasts.com/discuss/channels/javascript/add-links-to-typeahead-results

That may be my fault in the way I asked the question,

But I'm just trying to get an autocomplete search field set up and can't get Typeahead to add links to the results.

I'm starting to think there is a better autocomplete to use within a Laravel project, or at least on that is more current/has better support.

You guys are the best so I thought I would throw this out there.

I appreciate any help provided. Thanks so much!

0 likes
31 replies
Punksolid's avatar
Level 25

I think it's not specifically the answer you are looking for, but I think that what are you trying to achieve is a lot simpler with vuejs.

this vuejs component does something similar of what you want and is easy to use. I use it in one of my projects.

https://element.eleme.io/#/remote-search

Hope it helps

1 like
Snapey's avatar

None of the autocomplete tools I have used allow for links in the content. Normally these are filling a input field where it makes no sense for it to have a href in the input field value.

Perhaps the term is wrong. The site @punksolid recommends has a search box with selectable dropdown elements so perhaps its an interactive search tool that you want rather than 'autocomplete'?

WallyJ's avatar

@punksolid Thanks! I'll check that out and let you know what I go with.

@snapey Very good point. You are helping me rethink my functionality. I'm trying to make it easier on the user to look up a particular record.

Thank you both!

Robstar's avatar

I'm unsure why you'd use a plugin for something so simple. I'd personally use Vue for this.

1 like
WallyJ's avatar

@robstar You may very well be right. I have just never used Vue before, so it isn't as obvious to me.

I started using Laravel before Vue was used with it with regularity. But I appreciate the suggestion!

1 like
WallyJ's avatar

@snapey One other thought, for some applications, like looking up a Client Account by name, wouldn't it be easier for the end user to type in the name and when they see the correct name, to simply click on the name and it take them to the Client View, rather than clicking the name, then clicking "Submit" or "Search"?

This is the functionality I'm going for. Thanks!

1 like
Robstar's avatar

@WALLYJ - Fair enough. Even using plain JavaScript or jQuery it's pretty straightforwards to built yourself. There are a lot of jQuery plugins for this, but the majority of them are huge.

1 like
Robstar's avatar

@WALLYJ - You're looking to build an 'auto suggest' / 'auto complete' search feature. You'd want clickable suggestions to show as you type and a separate screen that displays all results if the user actually submits the search form.

1 like
WallyJ's avatar

@robstar Yes, though, I am trying to remove the step of them having to click a Search button after choosing a name.

For instance, there are online editors for websites that allow you to choose a font for some text.

You can either click the font dropdown arrow, or start typing in the input box. It autocompletes as you type, and once you see the name of the font you want to use, you click on it. Once you click, it immediately fills the box with the name of the font you chose, but it also changes the font of the text.

You don't have to search, then click on the font name, then ALSO click on a "Change Font" button.

Search, click, action occurs. No other buttons or manual form submissions.

That is my goal.

Type a name, click it, immediately sends that name to a route for me to open the index view for that record (or whatever else I might want to do with that value)

Make sense?

Robstar's avatar

@WALLYJ - You'd want to keep the button there, clickable for usability.

The autocomplete may suggests a small amount of recommended results, each of which can be clicked upon.

You'd also want to allow users to search and display all results on a separate page.

If you want things to happen when a user clicks the result (other than visiting a new url) I'd recommend Vue.

1 like
WallyJ's avatar

@punksolid @snapey @robstar

After taking the advice to consider Vue.js, I found a tutorial here: https://www.youtube.com/watch?v=NUx56WcFIRQ

that does exactly what I want from a functionality standpoint. However, I am learning that trying to mix VueJS and blade with @foreach loops, @if (session('status')) statements,etc. don't work in VueJS templates.

Do I have to leave all blade functionality in the app.blade.php file and use VueJS components for what goes inside that functionality, or should I use VueJS functions for loops and sessions?

I can't even get a VueJS template to render in a view.

I set the

Vue.component('admin', require('./components/Admin.vue').default);

in my app.js file.

Put a simple

<admin></admin>

in my index.blade.php file.

and it renders "admin/admin" on the page as text.

Feeling stuck. Any advice is appreciated.

UPDATE: I have learned that the VueJS component won't render with certain errors. When I commented out the @foreach statements and Sessions, it rendered. Now I just have to figure out if I want to switch completely to VueJS for loops and sessions. Any thoughts are appreciated.

Snapey's avatar

Did you include a parent element which is bound to Vue?

eg

<div id="app">

which is then bound in app.js;

const app = new Vue({
    el: '#app'
});
WallyJ's avatar

@snapey Yes.

This is in my index.blade.php. I should have been more verbose.

<div id="app">
    <admin></admin>
</div>

Again, it renders now. but only because I got rid of all errors.

WallyJ's avatar

@snapey Also,

Trying to convert

@foreach ($clients as $client)
     <div>{{$client->name}}</div>
@endforeach

over to VueJS is a pain, and then I have to figure out how to convert simple Auth functionality like

@if ($user->isAdmin())

is a lot of extra lines of code that I am struggling to begin to understand.

Quite frankly it seems that in the creation of Laravel and the blade syntax, the future movement toward Javascript use in the DOM was not considered enough.

It would be great if Jeffrey Way would pick one Javascript framework like VueJS and implement it into Laravel in a way that works within blade syntax so we could easily have both.

I've spent so much time learning Laravel, then learning Blade, only to learn that the newest functionality is found in VueJS or Angular or React, which breaks all of my training and work in using Blade templating all these years.

Again, should I just convert to VueJS away from Blade?

I found this article addressing VueJS and Auth -https://medium.com/@sadnub/vuejs-and-laravel-auth-part-2-5-d7c9d0263226

I found this article on converting @foreach statements in Blade to VueJS - https://vegibit.com/how-to-use-vuejs-with-laravel-blade/ Which seems to require an extra 9,000 lines of code to make it happen.

Here is another tutorial on how to use

So, the latest Laravel includes VueJS automatically, but it doesn't working in an integrated way with the Blade templating system.

And when you move to using VueJS, but need Auth functionality, you need to switch to something like JWT-Auth, as suggested by multiple tutorials, like this one: https://medium.com/@ripoche.b/create-a-spa-with-role-based-authentication-with-laravel-and-vue-js-ac4b260b882f Which includes another 7,532 lines of code to accomplish the Auth tasks.

Wasn't the point of Laravel to provide these types of functionality without a million lines of code we have to write?

I recall a few hundred Laravel videos saying "See how easy that was??" with Jeffrey Way touting the 3 lines of code that accomplished so much. With Javascript development in the forefront, pushing for more Single Page Apps, essentially spending 90% of our code making changes to the DOM, Laravel's functionality is getting left behind... it seems.

I'm not sure where to go from here.

willjohnathan's avatar

It is pretty easy to mix the two. I do it all the time until I decide I need complete reactivity to changing data. Something like this is what I do when quickly incorporating vue into an already working blade file:

@if ($user->isAdmin())
    <admin inline-template :clients="{{$clients}}">
        <div>
            <div v-for="client in clients" v-text="client.name"></div>
        </div>
    </admin>
@endif

This series has some great videos of going from fully blade to a little Vue to complete Vue once the need arises: https://laracasts.com/series/lets-build-a-forum-with-laravel

1 like
WallyJ's avatar

@willjohnathan If I I start mixing Blade and VueJS as you suggest, how do I deal with the Auth components? Did you move completely away from Laravel's built in Auth component to a JWS solution, or possible Laravel Passport?

willjohnathan's avatar

There are a lot of ways to handle it. I think the simplest / quickest for at least getting started would be to either leave the auth in the blade or pass the auth checks / user values as props to the component. You can also create a global user js variable such as:

window.App = {!! json_encode([
            'user' => Auth::user(),
            'signedIn' => Auth::check()
        ]) !!};
1 like
WallyJ's avatar

@willjohnathan So, if I understand correctly, I will simply need to insert VueJS components within Blade's functionality to use both as cleanly as possible, correct?

WallyJ's avatar

@willjohnathan I moved my auth back to the Blade template. This is all that's left in my Admin.vue file.

<template>
<table>
    <tr v-for="user in users" :key="user.id">
        <td>{{user.name}}</td>
    </tr>
</table>
</template>

<script>
    export default {
        data() {
            return {
                users : {}
            }
        },
        methods: {
            loadUsers() {
                axios.get("api/user").then(({ data}) => (this.users = data.data));
            }
        },

        created() {
            this.loadUsers();
        },
        mounted() {
            console.log('Component mounted.')
        }
    }
</script>

I'm receiving the following error in the javascript console:

GET http://newapp.test/api/user 401 (Unauthorized)
app.js:651 Uncaught (in promise) Error: Request failed with status code 401
    at createError (app.js:651)
    at settle (app.js:814)
    at XMLHttpRequest.handleLoad (app.js:184)

It seems to be something with the axios line, but I'm not sure what. Maybe something else.

willjohnathan's avatar

@WALLYJ - yes. You can add inline-template to your tag and you you can use both blade & vue variables and you wouldn't have a "template" tag in you vue component.

In the example I provided your vue component would look like this and it should work:

<script>
    export default {
    props = ['clients']
    }
</script>
1 like
willjohnathan's avatar

@WALLYJ - This error isn't related to vue... It is a server side error. Maybe your authentication has failed due to not being logged in? You still have access to all your Auth & Auth::user() data on the server side when doing an ajax request so you shouldn't be getting any additional errors, in case that is what you are thinking.

1 like
WallyJ's avatar

@WILLJOHNATHAN - It must have to do with view. I am logged in because my username from Auth shows in the upper right along with my Logout option.

It's Vue because the only information not showing on the page is from the Admin.vue file, called by:

<admin></admin>

And the error shows up in the Javascript console, not on the page itself like a Laravel error would show.

willjohnathan's avatar

@WALLYJ - No... check the network tab in the developer console. You are getting a bad response from "http://newapp.test/api/user". Your vue component is making this request and getting a bad response from your server. You should also be able to paste the url in your get request into the web browser address bar and see a "Laravel" error.

1 like
WallyJ's avatar

I guess my point is that the error is caused by this line, which is in the Vue file.

axios.get("api/user").then(({ data}) => (this.users = data.data))

And quite frankly, I don't know what this is doing since I copied this line as part of a tutorial I am watching. I know my db structure. There is a table called "users" with an "id" field and a "name" field.

Other than that I'm not sure how to fix this. I'm logged in, but something about the view file's request for the data has a permissions issue.

Do I need Laravel Passport for this to work?

WallyJ's avatar

It redirects me to my home route. No errors in the console

willjohnathan's avatar

ok... why is it redirecting you? you are making an ajax call to a route that redirects you (probably meaning the auth user does not have access to view this resource so I am going to redirect you home)??? If that is what you want, you can do a $request->expectsJson() check on the controller before the redirect and send an appropriate resonse. Then you would want to check for the response in your ajax callback and have it redirect you back home.

OR if you want it to provide actual user data and not redirect you, make it so that visiting that link (http://newapp.test/api/user) outputs json of the users instead of redirecting you when you visit it in the browser.

You can go back afterwards and clean it up so that it redirects you if you are not doing an ajax call. But that is the root of your problem right now.

1 like
WallyJ's avatar

@willjohnathan So, I installed Laravel Passport using the docs, then found this forum post: https://stackoverflow.com/questions/50193349/how-to-authenticate-vue-js-axios-request-of-an-api-route-in-laravel

where a guy found a note in the docs about using middleware to pass the token properly. I followed the solution example and now I don't get the 401 error any longer. No errors actually.

However, I don't see the data on the page yet, so I'm looking again at my axios syntax to see what may be wrong there.

I can click on the Network tab of the Inspection Console and see the "user" entry. When I click on it, and choose Preview, I see the first record of data, so the query is running properly.

Also, As I look at the code, the table tags show on the page. There is just nothing between them.

<table></table>

Not sure why this code isn't showing the data:

<table>
    <tr v-for="user in users" :key="user.id">
        <td>{{user.name}}</td>
    </tr>
</table>
Next

Please or to participate in this conversation.