patternjavascriptMinor
Typeahead / Autocomplete using AngularJS directive
Viewed 0 times
angularjsdirectivetypeaheadautocompleteusing
Problem
I am writing a Type-ahead / Autocomplete search with angular using directive and filter service. I am almost there but need your expert opinions on things which I am planning to achieve.
Git Repository
@Todos:
-
Look and feel
-
Allow navigation using keyboard
Could anyone review and suggest more optimize ways of writing this?
Also, shall I bind events within a parent controller scope or directive scope? Here is how my directive looks like:
HTML:
Template:
Git Repository
@Todos:
-
Look and feel
-
Allow navigation using keyboard
- Enter and Esc key handling
Could anyone review and suggest more optimize ways of writing this?
Also, shall I bind events within a parent controller scope or directive scope? Here is how my directive looks like:
var modServiceDef = angular.module('modSerDefinition', []);
modServiceDef.controller('modDefCtrl', ['$scope', 'myFactory', function($scope, myFactory) {
myFactory.getData().then(function (httpData) {
$scope.dataToPopulate = httpData;
},function(httpData) {
console.log('name retrieval failed.');
});
}
]);
modServiceDef.directive('typeAhead',[function() {
return {
scope : {
cinfo:'=datalist',
},
link:function(scope,element,attr) {
scope.visible = true;
scope.updateSearchTerm = function(selName) {
scope.sterm = selName;
}
},
templateUrl:'templates/typeahead.tmpl'
}
}]);
modServiceDef.factory('myFactory', function($http,$q) {
var factory = {};
var def = $q.defer();
factory.getData = function() {
$http.get('https://raw.githubusercontent.com/dominictarr/random-name/master/first-names.json')
.success(function(res){
factory.data = res;
def.resolve(res);
})
.error(function(err){
def.reject(err);
})
return def.promise;
}
return factory;
});HTML:
Template:
{{data}}
Solution
There are some points you could improve:
I would put the typeahead directive in an own module that you can include as a dependency to your app.
-
Your todos:
You can find my code in this fork. (If you like I could do a pull request in your repo.)
There are still the following possible improvements in the updated code:
- App structure:
I would put the typeahead directive in an own module that you can include as a dependency to your app.
angular.module('demoApp', ['pdTypeAhead']).- Click events: I think the best place is in the directive controller because they're there for your typeahead logic.
- Keyboard binding: You can add the mousetrap.js keyboard binding in a directive and add it in your typeahead
linkmethod. It's a bit tricky because you need to change the typeahead restrict to attribute (otherwise there is a problem with infinite digest loop.).
-
Your todos:
- look & feel: Twitter Bootstrap is a good starting point to do your styling.
- Keyboard navigation: You could do it with pure js but I think mousetrap.js is easier to use.
- Enter + Escape handling: Also use mousetrap. For event handling you could use
$scope.$brodcast('eventName', data)and catch it in your directive's controller with$scope.$on('eventName', function(data) { ... });
- Responsiveness: If you'd type the letter
ain your code it took pretty long to show the result (> 3000 matches). I think it's OK to limit the result to 100 or lower matches with alimitTofilter and the result is immediately visible.
You can find my code in this fork. (If you like I could do a pull request in your repo.)
There are still the following possible improvements in the updated code:
- Controller of the typeahead directive could be in it's own file. Improves readability.
- It's probably possible to put code from the typeahead controller into a service for refactoring.
- Escape key handling could be improved: After a click on a name you can't undo that click with a press on escape. But if you select with enter you can undo with escape.
- Directive template
typeahead.tmplcould be moved to the components folder of the directivejs/components/typeahead.
- Typeahead controller: Use
controllerAsinstead of$scope(if possible). Best practice, see style guide.
- Check if filtering is also possible directly in
ng-repeat? Should be possible and better. I've just moved it to js for easier debugging.
- Add options to typeahead, e.g. a way to enable or disable autofocus of search input directly in markup e.g. `
- Add a config provider
for options service so you could add the options application wide inside ofangular.module(...).config(...). This post is helpful for creating configurable directives.
- Add ng-blur` to close the typeahead if clicked outside.
- Add unit tests for the directive.
Context
StackExchange Code Review Q#94187, answer score: 3
Revisions (0)
No revisions yet.