Sunday 25 May 2014

Auto complete in Angular js

There are lot of examples are available on google for doing autocomplete. But the default angular js auto complete ( typeahead ) has some disadvantages. So I am going to discuss here about how to customize angular typeahead directive.

I have used angular js 1.2 ,angular-strap 0.7 js and twitter bootstrap .



<input type="text" class="autosuggesttextbox" bs-typeahead="datalists" >

 



$scope.datalists = data;

 

So our autocomplete is ready .Here you can see that it forces user to select default option or has to press esc key .It is not user friendly.

How to solve this issue



$.fn.typeahead.Constructor.prototype.render = function(items) {
    var that = this;
    items = $(items).map(function (i, item) {
      i = $(that.options.item).attr('data-value', item);
      i.find('a').html(that.highlighter(item));
      return i[0];
    });

    this.$menu.html(items);
    return this;
};

 

Now you can see it removed the default selection.

Now it is almost similar to google auto suggest .But you can see if you type something on the text box and hit enter key it will vanish .If you have a separate button it will work fine. But on enter key if you are not selecting any suggested options and auto complete box is available it assumes that the value is undefined. We can override this issue by customizing the angular strap directive.Go to angular strap.js and copy typeahead directive and rename to typeaheadcustomized ( or any name ).



angular.module('$strap.directives').directive('bsTypeaheadnew', [
'$parse',
function ($parse) {
return {
  restrict: 'A',
  require: '?ngModel',
  link: function postLink(scope, element, attrs, controller) {
 var getter = $parse(attrs.bsTypeaheadnew), setter = getter.assign,
 value = getter(scope);
 scope.$watch(attrs.bsTypeaheadnew, function (newValue, oldValue) {
   if (newValue !== oldValue) {
  value = newValue;
   }
 });
 element.attr('data-provide', 'typeahead');
 element.typeahead({
   source: function (query) {
  return angular.isFunction(value) ? value.apply(null, arguments)
  : value;
   },
   minLength: attrs.minLength || 1,
   items: attrs.items,
   updater: function (value) {
  if (controller) {
    scope.$apply(function () {
   if( !angular.isDefined(value)){
      value = $('.autosuggesttextbox').val();
     }
     controller.$setViewValue(value);
    });
  }
  scope.$emit('typeahead-updated', value);
  return value;
   }
 });
 var typeahead = element.data('typeahead');
 typeahead.lookup = function (ev) {
   var items;
   this.query = this.$element.val() || '';
   if (this.query.length < this.options.minLength) {
  return this.shown ? this.hide() : this;
   }
   items = $.isFunction(this.source) ? this.source(this.query,
   $.proxy(this.process, this)) : this.source;
   return items ? this.process(items) : this;
 };
 if (!!attrs.matchAll) {
   typeahead.matcher = function (item) {
  return true;
   };
 }
 if (attrs.minLength === '0') {
   setTimeout(function () {
  element.on('focus', function () {
    element.val().length === 0 && setTimeout(element.typeahead
    .bind(element, 'lookup'), 200);
  });
   });
 }
  }
};
}
]);

 

What we have done here is that we rename bs-typeahead to bs-typeaheadnew and added this if else condition



if( !angular.isDefined(value)){
  value = $('.autosuggesttextbox').val();
}


 

If value is undefined it will select from the text box

You can add min-length="2" to your text box for specifying when it should show auto complete.



<input type="text" class="autosuggesttextbox" min-length="2"
 bs-typeahead="datalists" >


 

References

1. Angular js

2. Angulat strap1.0

3. Angulat strap2.0.2

Related Posts

1. Communicate with controllers in angular js

2. Rating Stars using angular js Directive concept

3. Angular routing

4. Loop concept in angular js

5. Filtering concept in angular js

6. Auto complete using html5


1 comment :

  1. Please add Demo link, for better understanding

    ReplyDelete