Utiliser Typeahead.js de Twitter dans une application AngularJS

Si vous avez tenté d'utiliser le plugin JavaScript d'autocomplétion de Twitter, baptisé Typeahead.js, au sein d'une directive dans votre application AngularJS, d'une façon similaire à celle-ci :

angular.module('myDirectives', [])
.directive('initTypeahead', function() {
return function(scope, element, attrs) {
element.typeahead({
// ...
});
};
});

...vous avez peut-être eu la désagréable surprise de constater que lors de la sélection d'une valeur par l'utilisateur, la variable du $scope Angular définie en tant que modèle de l'input sur lequel vous avez appliqué la directive précédente ne se mettait pas correctement à jour, conservant pour toute valeur les quelques lettres saisies au préalable.

Typeahead mettant à notre disposition des évènements JavaScript permettant de détecter ladite sélection, le réflexe primordial et naïf (c'est du vécu) sera d'appliquer manuellement un $scope.apply() dans le listener adéquat :

angular.module('myDirectives', [])
.directive('initTypeahead', function() {
return function(scope, element, attrs) {
element.typeahead({
// ...
}).on('typeahead:selected typeahead:autocompleted', function() {
scope.$apply();
});
};
});

Hélas, le souci étant bien localisé dans l'actualisation du $scope depuis la vue (et non l'inverse), ceci se révèlera insuffisant pour appliquer la bonne valeur depuis le DOM, avec lequel nous serons obligés d'interagir :

angular.module('myDirectives', [])
.directive('initTypeahead', function() {
return function(scope, element, attrs) {
element.typeahead({
// ...
}).on('typeahead:selected typeahead:autocompleted', function(data) {
scope[element.data('ng-model')] = data.target.value;
scope.$apply();
});
};
});

Cette astuce vous évitera une imbrication plus profonde (passant par exemple par l'écriture d'un service dédié au sein de votre application), ce qui se traduira par un précieux gain de temps si vous n'utilisez cette bibliothèque que pour répondre à un besoin ponctuel.