From ccaa6272eb1bd8e3b447e3245ec24b81981c7aac Mon Sep 17 00:00:00 2001 From: Wesley Cho Date: Sat, 27 Jun 2015 15:23:56 -0700 Subject: [PATCH] fix(typeahead): add support for ngModelOptions getterSetter - Add support for getterSetter with ngModelOptions Closes #3865 Fixes #3823 --- src/typeahead/test/typeahead.spec.js | 13 +++++++++++++ src/typeahead/typeahead.js | 21 ++++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/typeahead/test/typeahead.spec.js b/src/typeahead/test/typeahead.spec.js index d31a8183dc..601b13becb 100644 --- a/src/typeahead/test/typeahead.spec.js +++ b/src/typeahead/test/typeahead.spec.js @@ -809,6 +809,19 @@ describe('typeahead tests', function() { expect($scope.test.typeahead.$error.parse).toBeUndefined(); }); + + it('issue #3823 - should support ng-model-options getterSetter', function() { + function resultSetter(state) { + return state; + } + $scope.result = resultSetter; + var element = prepareInputEl('
'); + + changeInputValueTo(element, 'Alaska'); + triggerKeyDown(element, 13); + + expect($scope.result).toBe(resultSetter); + }); }); describe('input formatting', function() { diff --git a/src/typeahead/typeahead.js b/src/typeahead/typeahead.js index 7c45b1ad2a..08c8afc423 100644 --- a/src/typeahead/typeahead.js +++ b/src/typeahead/typeahead.js @@ -34,8 +34,10 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) var eventDebounceTime = 200; return { - require: 'ngModel', - link: function(originalScope, element, attrs, modelCtrl) { + require: ['ngModel', '^?ngModelOptions'], + link: function(originalScope, element, attrs, ctrls) { + var modelCtrl = ctrls[0]; + var ngModelOptions = ctrls[1]; //SUPPORTED ATTRIBUTES (OPTIONS) //minimal no of characters that needs to be entered before typeahead kicks-in @@ -74,7 +76,16 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) //INTERNAL VARIABLES //model setter executed upon match selection - var $setModelValue = $parse(attrs.ngModel).assign; + var parsedModel = $parse(attrs.ngModel); + var invokeModelSetter = $parse(attrs.ngModel + '($$$p)'); + var $setModelValue = function(scope, newValue) { + if (angular.isFunction(parsedModel(originalScope)) && + ngModelOptions && ngModelOptions.$options && ngModelOptions.$options.getterSetter) { + return invokeModelSetter(scope, {$$$p: newValue}); + } else { + return parsedModel.assign(scope, newValue); + } + }; //expressions used by typeahead var parserResult = typeaheadParser.parse(attrs.typeahead); @@ -89,8 +100,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position']) //create a child scope for the typeahead directive so we are not polluting original scope //with typeahead-specific data (matches, query etc.) var scope = originalScope.$new(); - var offDestroy = originalScope.$on('$destroy', function(){ - scope.$destroy(); + var offDestroy = originalScope.$on('$destroy', function() { + scope.$destroy(); }); scope.$on('$destroy', offDestroy);