AngularJs UI typeahead match on leading characters

The typeahead functionality in AngularJs UI seems simple and powerful however I have been trying to figure out how to get the matching to be done on the leading characters. For example if I type ‘A’ in the input box I would like to see all the states that start with ‘A” and not all the states that contain an ‘A’ in the name. I have been looking for a couple of days on this and it seems that Angular has the concept of a custom filter that has a ‘comparator’. The docs on this have a simple example that does not show the exact syntax for implementing a comparator.

The html looks like this:

  • angularjs tab key press prevent default
  • Angular UI Router - Views in an Inherited State
  • Angular ui-router: Can you change state without changing URL?
  • Deferring angular controllers until Ajax call is completed
  • Angular - no method sortable
  • Unit testing angular-bootstrap $modal
  • <div>Selected: <span>{{selected}}</span></div>
        <div><input type="text" ng-model="selected" typeahead="name for name in states | filter:selected"></div>
    

    The basic javascript looks like this

    angular.module('firstChar', ['ui.bootstrap']);
    
        function TypeaheadCtrl($scope) {
            $scope.selected = undefined;
            $scope.states = ['Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Dakota', 'North Carolina', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming'];
        }
    

    I have a plunker here http://plnkr.co/edit/LT6pAnS8asnpFEd5e6Ri

    So the challenge in a nutshell is to get the AngularUI typeahead to match only on the leading characters.

    Any help or ideas on this would be hugely appreciated.

  • AngularJs templates not loading in internet explorer 8
  • ng-bind-html - with angular-sanitize - throws error in console
  • ANGULAR-UI-ROUTER: Resolve state from URL
  • Is there any way to get a list of child states in angular-ui-router?
  • Does ng-grid supports cell filter (angular filter) by row
  • Angular ui-select tagging lose text input on blur
  • 3 Solutions collect form web for “AngularJs UI typeahead match on leading characters”

    At the end of the day your question is not really specific to the typeahead directive but it has more to do with how AngularJS filters work.

    Before presenting a working solution please note that the typeahead directive makes heavy use of AngularJS infrastructure ($http, promises) and expression language. So it is important to realize that the states | filter:selected is nothing more that an AngularJS expression.

    Having a look at the above expression we need to find a way of filtering an array to return a list of matching items. The only special thing about the typeahead directive is that there is a $viewValue variable representing a value entered by a user in the input box. So we basically just need to filter the states array to return items starting with the $viewValue.

    There are many ways of doing this but since you’ve mentioned the comparator for filters (please note that those were only introduced in 1.1.x version of AngularJS) you would have to define a comparator function that should decide if a given item should be returned in the list of results or not. Such a function could look like follows:

    $scope.startsWith = function(state, viewValue) {
      return state.substr(0, viewValue.length).toLowerCase() == viewValue.toLowerCase();
    } 
    

    Having it defined the usage is very simple:

    typeahead="name for name in states | filter:$viewValue:startsWith"
    

    Here is the working plunk: http://plnkr.co/edit/WWWEwU4oPxvbN84fmAl0?p=preview

    Custom filter for get the matching to be done on the leading characters in typehead auto completion box.

    (function() {
    
        // Create global filters using angular.filter() only. Never use local filters inside
        // controllers/services. This enhances testing and reusability.
        function xpTypeaheadFilter() {
              return function(items, props) {
    
                var out = [];
                
                if (angular.isArray(items)) {
    
                  items.forEach(function(item) {
                    
                    
    
    
                    var text = props.toLowerCase();
                    var itemLoverCase =item.toLowerCase();
                    var substr = itemLoverCase.substr(0, text.length);
    
                     
                    if (substr === text ) {
                        
                         out.push(item);
                         
                    }
                    
    
                  });
                } else {
                  // Let the output be the input untouched
                  out = items;
                }
                console.log("out lem", out.length);
    
                return out;
              };
        }
    
        // Pass functions into module methods rather than assigning a callback.
        // This helps aid with readability and helps reduced the amount of code "wrapped"
        // inside Angular.
        angular.module('common')
        .filter('xpTypeaheadFilter', xpTypeaheadFilter);
    })();
    <input type="text" ng-model="vesselName" placeholder="Vessel Name" typeahead="vesselName for vesselName in vesselNames | xpTypeaheadFilter:$viewValue | limitTo:8"  class="form-control form-textbox" >

    I just edited post marked as answered and it works when list is having Id and title both:

    <input type="text" ng-model="ledgerstatementModel.Supplier" typeahead="supplier as supplier.Name for supplier in supplierList | filter:{Name:$viewValue}:startsWith" class="form-control">
    

    and in js :

     $scope.startsWith = function (supplier, viewValue) {
            return supplier.substr(0, viewValue.length).toLowerCase() == viewValue.toLowerCase();
        }