Home >Web Front-end >JS Tutorial >Creating a Typeahead Widget with AngularJS - SitePoint
<span>var typeAhead = angular.module('app', []); </span> typeAhead<span>.factory('dataFactory', function($http) { </span> <span>return { </span> <span>get: function(url) { </span> <span>return $http.get(url).then(function(resp) { </span> <span>return resp.data; // success callback returns this </span> <span>}); </span> <span>} </span> <span>}; </span><span>});</span>The previous code creates a factory called dataFactory that retrieves JSON data from an API. We won’t go into the details of the factory, but we need to briefly understand how the $http service works. You pass a URL to the get() function, which returns a promise. Another call to then() on this promise also returns another promise (we return this promise from the factory’s get() function). This promise is resolved with the return value of the success callback passed to then(). So, inside our controller, we don’t directly interact with $http. Instead, we ask for an instance of factory in the controller and call its get() function with a URL. So, our controller code that interacts with the factory looks like this:
typeAhead<span>.controller('TypeAheadController', function($scope<span>, dataFactory</span>) { // DI in action </span> dataFactory<span>.get('states.json').then(function(data) { </span> $scope<span>.items = data; </span> <span>}); </span> $scope<span>.name = ''; // This will hold the selected item </span> $scope<span>.onItemSelected = function() { // this gets executed when an item is selected </span> <span>console.log('selected=' + $scope.name); </span> <span>}; </span><span>});</span>The previous code uses an API endpoint called states.json that returns a JSON list of US States. When the data is available, we store the list in the scope model items. We also use the model name to hold the selected item. Finally, the function onItemSelected() gets executed when the user selects a particular state.
typeAhead<span>.directive('typeahead', function($timeout) { </span> <span>return { </span> <span>restrict: 'AEC', </span> <span>scope: { </span> <span>items: '=', </span> <span>prompt: '@', </span> <span>title: '@', </span> <span>subtitle: '@', </span> <span>model: '=', </span> <span>onSelect: '&' </span> <span>}, </span> <span>link: function(scope<span>, elem, attrs</span>) { </span> <span>}, </span> <span>templateUrl: 'templates/templateurl.html' </span> <span>}; </span><span>});</span>In the directive we are creating an isolated scope that defines several properties:
<span>var typeAhead = angular.module('app', []); </span> typeAhead<span>.factory('dataFactory', function($http) { </span> <span>return { </span> <span>get: function(url) { </span> <span>return $http.get(url).then(function(resp) { </span> <span>return resp.data; // success callback returns this </span> <span>}); </span> <span>} </span> <span>}; </span><span>});</span>
typeAhead<span>.controller('TypeAheadController', function($scope<span>, dataFactory</span>) { // DI in action </span> dataFactory<span>.get('states.json').then(function(data) { </span> $scope<span>.items = data; </span> <span>}); </span> $scope<span>.name = ''; // This will hold the selected item </span> $scope<span>.onItemSelected = function() { // this gets executed when an item is selected </span> <span>console.log('selected=' + $scope.name); </span> <span>}; </span><span>});</span>First, we render an input text field where the user will type. The scope property prompt is assigned to the placeholder attribute. Next, we loop through the list of states and display the name and abbreviation properties. These property names are configured via the title and subtitle scope properties. The directives ng-mouseenter and ng-class are used to highlight the entry when a user hovers with the mouse. Next, we use filter:model, which filters the list by the text entered into the input field. Finally, we used the ng-hide directive to hide the list when either the input text field is empty or the user has selected an item. The selected property is set to true inside the handleSelection() function, and set to false false (to show the suggestions list) when someone starts typing into the input field.
typeAhead<span>.directive('typeahead', function($timeout) { </span> <span>return { </span> <span>restrict: 'AEC', </span> <span>scope: { </span> <span>items: '=', </span> <span>prompt: '@', </span> <span>title: '@', </span> <span>subtitle: '@', </span> <span>model: '=', </span> <span>onSelect: '&' </span> <span>}, </span> <span>link: function(scope<span>, elem, attrs</span>) { </span> <span>}, </span> <span>templateUrl: 'templates/templateurl.html' </span> <span>}; </span><span>});</span>The function handleSelection() updates the scope property, model, with the selected state name. Then, we reset the current and selected properties. Next, we call the function onSelect(). A delay is added because the assignment scope.model=selecteditem does not update the bound controller scope property immediately. It is desirable to execute the controller scope callback function after the model has been updated with the selected item. That’s the reason we have used a $timeout service. Furthermore, the functions isCurrent() and setCurrent() are used together in the template to highlight entries in the auto complete suggestion. The following CSS is also used to complete the highlight process.
<span>{ </span> <span>"name": "Alabama", </span> <span>"abbreviation": "AL" </span><span>}</span>
<span><span><span><input</span> type<span>="text"</span> ng-model<span>="model"</span> placeholder<span>="{{prompt}}"</span> ng-keydown<span>="selected=false"</span> /></span> </span><span><span><span><br</span>/></span> </span> <span><span><span><div</span> class<span>="items"</span> ng-hide<span>="!model.length || selected"</span>></span> </span> <span><span><span><div</span> class<span>="item"</span> ng-repeat<span>="item in items | filter:model track by $index"</span> ng-click<span>="handleSelection(item[title])"</span> <span>style<span>="<span>cursor:pointer</span>"</span></span> ng-class<span>="{active:isCurrent($index)}"</span> ng-mouseenter<span>="setCurrent($index)"</span>></span> </span> <span><span><span><p</span> class<span>="title"</span>></span>{{item[title]}}<span><span></p</span>></span> </span> <span><span><span><p</span> class<span>="subtitle"</span>></span>{{item[subtitle]}}<span><span></p</span>></span> </span> <span><span><span></div</span>></span> </span><span><span><span></div</span>></span></span>
Customizing the appearance of the typeahead dropdown can be achieved by using CSS. You can target the dropdown menu by using the class .dropdown-menu. For instance, if you want to change the background color and font color, you can use the following CSS code:
.dropdown-menu {
background-color: #f8f9fa;
color: #343a40;
}
Remember to include this CSS in your main CSS file or within the
Limiting the number of suggestions in the typeahead dropdown can be done by using the typeahead-min-length attribute. This attribute specifies the minimum number of characters that must be entered before typeahead starts to kick in. For example, if you want to start showing suggestions after the user has typed 3 characters, you can use the following code:
To use an object selection functionality with typeahead, you can use the typeahead-on-select attribute. This attribute allows you to specify a function to be called when a match is selected. The function will be passed the selected item. For example:
In your controller, you can define the onSelect function like this:
$scope.onSelect = function (item, model, label) {
// Do something with the selected item
};
To use typeahead with Bootstrap in AngularJS, you need to include the ui.bootstrap module in your AngularJS application. This module provides a set of AngularJS directives based on Bootstrap’s markup and CSS. The typeahead directive can be used as follows:
In this example, states is an array of states, $viewValue is the value entered by the user, and limitTo:8 limits the number of suggestions to 8.
To use typeahead with remote data in AngularJS, you can use the $http service to fetch data from a remote server. The typeahead attribute can be used to bind the input field to the fetched data. For example:
$scope.getStates = function(val) {
return $http.get('/api/states', {
params: {
name: val
}
}).then(function(response){
return response.data.map(function(item){
return item.name;
});
});
};
In your HTML, you can use the getStates function like this:
In this example, getStates is a function that fetches states from a remote server based on the value entered by the user.
The above is the detailed content of Creating a Typeahead Widget with AngularJS - SitePoint. For more information, please follow other related articles on the PHP Chinese website!