DaShak's avatar

autocomplete form text field suggestions from values in database?

Hi folks,

I'm relatively new to Laravel and finding Laracasts to be indispensable. This is my first forum post, so please forgive me if I overlooked something.

I've built some forms into a new application that I started from scratch with Laravel and following the Intermediate series of videos.

There is a search form, which I would like to offer suggestions to auto-complete text fields, particularly the name field, and I would like the suggestions to be generated by existing values already stored in the database.

Can anyone please refer me to HOWTOs/videos/demos/examples that I can follow to expedite my development?

I figure that I need

  1. a route/endpoint to query the database based on text input, and
  2. some AJAX to relay & display the front-end input to back-end for query

I'm looking for something describing standard best-practices to follow (as per the Laracasts in general) so I can reduce my errors and develop in a most comprehensible & efficient way possible.

Regards, Shak

0 likes
3 replies
RachidLaasri's avatar

You need to create a table for searches something like :

  • Search
    • id
    • keywords
    • user_id ( can be null )
    • date

So when a user search for something it will be saved to that table. You will need this data to create the auto-complete feature. You will need to use of of the jQuery autocomplte plugins like this one https://github.com/devbridge/jQuery-Autocomplete , and post to a route that will give you the json data, let's say "fetch-data" for example :

Route::post('fetch-data', 'SearchController@search');

And your search method

public function search(Request $request)
{
    $keywords = $request->get('keywords');

    $suggestions = Search::where('keywords', 'LIKE', '%'.$keywords.'%')->get();

    return $suggestions;
}

$keywords is the string the user currently typed, you'll pass that with the post request.

1 like
DaShak's avatar

Thanks for your reply @RachidLaasri - I'm not sure why I need a table as I would like the autocomplete's searches to be done on-the-fly and have no intention of saving a User's search parameters - I understand the technicalities but am still looking for a complete walk-through along the lines of Laracasts' other videos...

auroralabs's avatar

HI,

For this I was using the webpatser/countries composer package that sets up a table in the database called countries and is pulling data forn the row "name". I am also using an autocomplete javascript library. You would in your case just replace the Table/Row names from your database table.

Create your controller

<?php namespace App\Http\Controllers\Frontend\Pages;
use App\Http\Requests;
use App\Http\Controllers\Controller;


class JsonController extends Controller
{
    public function getLocation($query)
    {
        $data = array();
        $results = \Countries::select('name')
            ->where('name', 'LIKE',  '%' . $query . '%')
            ->get();

        foreach ( $results as $result ):
            $data[] = $result->name;
        endforeach;

        var_dump($data);
        //return \Response::json($data);
    }
}

Add a Route to test your output in the browser. Using firebug of similar you will get a 200 response with some data. ie www.domain.com/location/aus

Route::group(['namespace' => 'Pages'], function ()
{
    Route::get('location/{query}', [
        'as' => 'location_path',
        'uses' => 'JsonController@getLocation'
    ]);
});

If all is well use it in your form with some autocomplete library in this case I am using typehead with jQuery. Ensure the ID field is set as you willneed this for the Java side..

<div class="form-group has-feedback">
    <div class="col-lg-8">
        {!! Form::text('director1_country', $value = old('director1_country'), [
            'placeholder'   => 'Start Typing for Suggestions',
            'id'            => 'director1_country',
            'class'         => 'form-control',
            'required'      => 'required',
            'autofocus'     => 'autofocus'
            ]) !!}
        <i style="display: none;" class="form-control-feedback" data-bv-icon-for="director1_country"></i>
    </div>
</div>

Finally add the Javascript libraries to your page and add the custom script as below last or visit the vendor website for more options to format your data.. The variable country_list can be changed to whatever you want as this just identifies it from other you may have. The remote is whatever you have set you route to as this will be used in your form to display the data.

var country_list = new Bloodhound({
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name'),
    queryTokenizer: Bloodhound.tokenizers.whitespace,
    limit: 10,
    remote: {
        url: '/location/%QUERY',
        filter: function(list) {
            return $.map(list, function(country) { return { name: country }; });
        }
    }
});
country_list.initialize();
$("#director1_country").typeahead({
    hint: true,
    highlight: true,
    minLength: 3
}, {
    source: country_list.ttAdapter(),
    name: 'country_list',
    displayKey: 'name',
    templates: {
        empty: [
            '<div class="empty-message">unable to find any country with that name.</div>'
        ]
    }
});

Please or to participate in this conversation.