Typeahead Widget Typeahead.php

Thankful to Krajee!
to get more out of us.

NOTE: This extension depends on the yiisoft/yii2-bootstrap extension. Check the composer.json for this extension's requirements and dependencies that may be updated by composer.

The Typeahead widget is a Yii 2 wrapper for for the Twitter Typeahead.js plugin with certain custom enhancements. This input widget is a jQuery based replacement for text inputs providing search and typeahead functionality. It is inspired by twitter.com's autocomplete search functionality and based on Twitter's typeahead.js, which is described as a fast and fully-featured autocomplete library. The widget is specially styled for Bootstrap 3. The widget allows graceful degradation to a normal HTML text input, if the browser does not support JQuery. You can setup model validation rules for a model attribute that uses TypeaheadBasic widget for input like any other field.

Note

The Typeahead widget is an advanced implementation of the typeahead.js plugin with the BloodHound suggestion engine and the Handlebars template compiler


This widget is an advanced implementation of the typeahead.js plugin with the BloodHound suggestion engine and the Handlebars template compiler.

The widget supports all parameters that one would pass for any Yii Input Widget. The additional parameter settings specially available for the Typeahead widget configuration are:
  • scrollable: boolean whether the dropdown menu is to be made scrollable. Defaults to false.

  • rtl: boolean whether the enable RTL (right to left) input support. Defaults to false.

  • dataset: array the main Typeahead object for defining a set of data that hydrates suggestions. It consists of the following special variable settings:

    • local: array configuration for the local list of datums. You must set one of local, prefetch, or remote.

    • prefetch: array configuration for the prefetch options object. Refer documentation for the options you can set for this parameter. The return data must be Json encoded and converted to an associative array of the format [['value' => 'data1'], ['value' => 'data2'],...], where value is the fixed key set in displayKey.

    • remote: array configuration for the remote options object. Refer documentation for the options you can set for this parameter. The return data must be Json encoded and converted to an associative array of the format [['value' => 'data1'], ['value' => 'data2'],...], where value is the fixed key set in displayKey.

    • limit: integer the max number of suggestions from the dataset to display for a given query. Defaults to 5.

    • displayKey: string for a given suggestion object, determines the string representation of it. This will be used when setting the value of the input control after a suggestion is selected. Can be either a key string or a function that transforms a suggestion object into a string. Defaults to value.

    • templates: array the templates used for rendering suggestions. Can be a string or a pre-compiled template (i.e. a yii\web\JsExpression function that takes a datum as input and returns html as output). If not provided, defaults to <p>{{value}}</p>

      • empty – Rendered when 0 suggestions are available for the given query. Can be either a HTML string or a precompiled template. If it's a precompiled template, the passed in context will contain query.

      • footer– Rendered at the bottom of the dataset. Can be either a HTML string or a precompiled template. If it's a precompiled template, the passed in context will contain query and isEmpty.

      • header – Rendered at the top of the dataset. Can be either a HTML string or a precompiled template. If it's a precompiled template, the passed in context will contain query and isEmpty.

      • suggestion – Used to render a single suggestion. If set, this has to be a precompiled template. The associated suggestion object will serve as the context. Defaults to the value of displayKey wrapped in a p tag i.e. <p>{{value}}</p>. The widget includes the Handlebars template compiler loaded by default. Check the advanced usage section on using this.

  • options: array the HTML attributes for the widget input tag.

  • container: array the HTML attributes for the container enclosing the input. You can set your own CSS classes here for stylin the dropdown when using templates.

  • pluginOptions: array the options for the typeahead.js plugin. The following options can be configured:

    • highlight – If true, when suggestions are rendered, pattern matches for the current query in text nodes will be wrapped in a strong element. Defaults to false.

    • hint – If false, the typeahead will not show a hint. Defaults to true.

    • minLength – The minimum character length needed before suggestions start getting rendered. Defaults to 1.

  • pluginEvents: array the Typeahead JQuery events. You must define events in event-name => event-function format. All events will be stacked in the sequence. Refer the plugin events documentation for details. For example:

    pluginEvents = [
        "typeahead:opened" => "function() { log("typeahead:opened"); }",
        "typeahead:closed" => "function() { log("typeahead:closed"); }",
        "typeahead:cursorchanged" => "function() { log("typeahead:cursorchanged"); }",
        "typeahead:selected" => "function() { log("typeahead:selected"); }",
        "typeahead:autocompleted" => "function() { log("typeahead:autocompleted"); }",
    ];
    

Note:

The return data for prefetch or local in the examples below must return a JSON encoded associative array of the format [['value' => 'data1'], ['value' => 'data2'],...], where value is the fixed key set in displayKey

.

Usage with ActiveForm and model (with search term highlighting)

With a model and without ActiveForm (with search term highlighting)

Usage without a model (with search term highlighting)

A disabled typeahead input

use kartik\widgets\Typeahead

// Usage with ActiveForm and model (with search term highlighting)
echo $form->field($model, 'state_3')->widget(Typeahead::classname(), [
    'options' => ['placeholder' => 'Filter as you type ...'],
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'local' =>  $data,
            'limit' => 10
        ]
    ]
]);

// With a model and without ActiveForm (with search term highlighting)
echo '<label class="control-label">State</label>';
echo Typeahead::widget([
    'model' => $model, 
    'attribute' => 'state_4',
    'options' => ['placeholder' => 'Filter as you type ...'],
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'local' =>  $data,
            'limit' => 10
        ]
    ]
]);

// Usage without a model (with search term highlighting)
echo '<label class="control-label">State</label>';
echo Typeahead::widget([
    'name' => 'state_10',
    'options' => ['placeholder' => 'Filter as you type ...'],
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'local' =>  $data,
            'limit' => 10
        ]
    ]
]);

// A disabled typeahead input
echo '<label class="control-label">State</label>';
echo Typeahead::widget([
    'name' => 'state_11',
    'options' => [
        'disabled' => 'disabled',
        'placeholder' => 'Filter as you type ...',
    ],
    'dataset' => [
        [
            'local' =>  $data,
            'limit' => 10
        ]
    ]
]);

Note:

The return data for prefetch or remote in the examples below must be return a JSON encoded associative array of the format [['value' => 'data1'], ['value' => 'data2'],...], where value is the fixed key set in displayKey

.

Remote json call (ajax) via controller action along with a scrollable dropdown

Right to Left (RTL) input support

Defines a custom template with a Handlebars compiler for rendering suggestions

Two datasets that are prefetched, stored, and searched on the client

Prefetches some data then relies on remote requests for suggestions when prefetched data is insufficient.

use kartik\widgets\Typeahead;
use yii\helpers\Url;

// Remote json call (ajax) via controller action along with a scrollable dropdown
echo '<label class="control-label">Select Country</label>';
echo Typeahead::widget([
    'name' => 'country_1',
    'options' => ['placeholder' => 'Filter as you type ...'],
    'scrollable' => true,
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'prefetch' => Url::to(['site/country-list']),
            'limit' => 10
        ]
    ]
]);

// Right to Left (RTL) input support
echo '<label class="control-label">Select Country</label>';
echo Typeahead::widget([
    'name' => 'country_30',
    'options' => ['placeholder' => 'Filter as you type ...'],
    'scrollable' => true,
    'rtl' => true,
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'prefetch' => Url::to(['site/country-list']),
            'limit' => 10
        ]
    ]
]);

// Defines a custom template with a <code>Handlebars</code> compiler for rendering suggestions
echo '<label class="control-label">Select Repository</label>';
$template = '<p class="repo-language">{{language}}</p>' .
    '<p class="repo-name">{{name}}</p>' .
    '<p class="repo-description">{{description}}</p>';
echo Typeahead::widget([
    'name' => 'twitter_oss', 
    'options' => ['placeholder' => 'Filter as you type ...'],
    'dataset' => [
        [
            'prefetch' => $baseUrl . '/samples/repos.json',
            'templates' => [
                'empty' => '<div class="text-error">Unable to find repositories for selected query.</div>',
                'suggestion' => new JsExpression("Handlebars.compile('{$template}')")
            ] 
        ]
    ]
]);

// Two datasets that are prefetched, stored, and searched on the client
echo Typeahead::widget([
    'name' => 'sports',
    'options' => ['placeholder' => 'Filter as you type ...'],
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'prefetch' => $baseUrl . '/samples/nba.json',
            'templates' => [
                'header' => '<h3 class="league-name">NBA Teams</h3>'
            ]
        ],
        [
            'prefetch' => $baseUrl . '/samples/nhl.json',
            'templates' => [
                'header' => '<h3 class="league-name">NHL Teams</h3>'
            ]
        ]
    ]
]);

/**
 * Prefetches some data then relies on remote requests for 
 * suggestions when prefetched data is insufficient. 
 * The prefetch source is: 
 * ["Andorra", "United Arab Emirates", "Afghanistan", "Antigua and Barbuda", "Anguilla", "Albania"]
 */
echo Typeahead::widget([
    'name' => 'country',
    'options' => ['placeholder' => 'Filter as you type ...'],
    'pluginOptions' => ['highlight'=>true],
    'dataset' => [
        [
            'prefetch' => $baseUrl . '/samples/countries.json',
            'remote' => Url::to(['site/country-list']) . '?q=%QUERY',
            'limit' => 10
        ]
    ]
]);

/** 
 * Your controller action to fetch the list
 */
public function actionCountryList($q = null) {
    $query = new Query;
    
    $query->select('name')
        ->from('country')
        ->where('name LIKE "%' . $q .'%"')
        ->orderBy('name');
    $command = $query->createCommand();
    $data = $command->queryAll();
    $out = [];
    foreach ($data as $d) {
        $out[] = $d['name'];
    }
    echo Json::encode($out);
}