HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

Typeahead / Autocomplete using AngularJS directive

Submitted by: @import:stackexchange-codereview··
0
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

  • 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:

  • 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 link method. 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 a in 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 a limitTo filter 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.tmpl could be moved to the components folder of the directive js/components/typeahead.



  • Typeahead controller: Use controllerAs instead 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 of angular.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.