Skip to content
This repository was archived by the owner on May 29, 2019. It is now read-only.

Commit ea1e858

Browse files
fix(typeahead): separate text field rendering and drop down rendering
Closes #240 Closes #274
1 parent c4e169c commit ea1e858

File tree

2 files changed

+44
-11
lines changed

2 files changed

+44
-11
lines changed

src/typeahead/test/typeahead.spec.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ describe('typeahead tests', function () {
279279
});
280280
});
281281

282-
describe('integration with existing formatters', function () {
282+
describe('input formatting', function () {
283283

284284
it('should co-operate with existing formatters', function () {
285285

@@ -290,6 +290,20 @@ describe('typeahead tests', function () {
290290

291291
expect(inputEl.val()).toEqual('formatted' + $scope.result.name);
292292
});
293+
294+
it('should support a custom input formatting function', function () {
295+
296+
$scope.result = $scope.states[0];
297+
$scope.formatInput = function($model) {
298+
return $model.code;
299+
};
300+
301+
var element = prepareInputEl("<div><input ng-model='result' typeahead-input-formatter='formatInput($model)' typeahead='state as state.name for state in states | filter:$viewValue'></div>"),
302+
inputEl = findInput(element);
303+
304+
expect(inputEl.val()).toEqual('AL');
305+
expect($scope.result).toEqual($scope.states[0]);
306+
});
293307
});
294308

295309
});

src/typeahead/typeahead.js

+29-10
Original file line numberDiff line numberDiff line change
@@ -37,24 +37,34 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
3737
require:'ngModel',
3838
link:function (originalScope, element, attrs, modelCtrl) {
3939

40-
var $setModelValue = $parse(attrs.ngModel).assign;
40+
//SUPPORTED ATTRIBUTES (OPTIONS)
4141

4242
//minimal no of characters that needs to be entered before typeahead kicks-in
4343
var minSearch = originalScope.$eval(attrs.typeaheadMinLength) || 1;
4444

4545
//minimal wait time after last character typed before typehead kicks-in
4646
var waitTime = originalScope.$eval(attrs.typeaheadWaitMs) || 0;
4747

48-
//expressions used by typeahead
49-
var parserResult = typeaheadParser.parse(attrs.typeahead);
50-
5148
//should it restrict model values to the ones selected from the popup only?
5249
var isEditable = originalScope.$eval(attrs.typeaheadEditable) !== false;
5350

51+
//binding to a variable that indicates if matches are being retrieved asynchronously
5452
var isLoadingSetter = $parse(attrs.typeaheadLoading).assign || angular.noop;
5553

54+
//a callback executed when a match is selected
5655
var onSelectCallback = $parse(attrs.typeaheadOnSelect);
5756

57+
var inputFormatter = attrs.typeaheadInputFormatter ? $parse(attrs.typeaheadInputFormatter) : undefined;
58+
59+
//INTERNAL VARIABLES
60+
61+
//model setter executed upon match selection
62+
var $setModelValue = $parse(attrs.ngModel).assign;
63+
64+
//expressions used by typeahead
65+
var parserResult = typeaheadParser.parse(attrs.typeahead);
66+
67+
5868
//pop-up element used to display matches
5969
var popUpEl = angular.element('<typeahead-popup></typeahead-popup>');
6070
popUpEl.attr({
@@ -147,16 +157,25 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position'])
147157
});
148158

149159
modelCtrl.$formatters.push(function (modelValue) {
160+
150161
var candidateViewValue, emptyViewValue;
151162
var locals = {};
152-
locals[parserResult.itemName] = modelValue;
153163

154-
//it might happen that we don't have enough info to properly render input value
155-
//we need to check for this
156-
candidateViewValue = parserResult.viewMapper(originalScope, locals);
157-
emptyViewValue = parserResult.viewMapper(originalScope, {});
164+
if (inputFormatter) {
158165

159-
return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;
166+
locals['$model'] = modelValue;
167+
return inputFormatter(originalScope, locals);
168+
169+
} else {
170+
locals[parserResult.itemName] = modelValue;
171+
172+
//it might happen that we don't have enough info to properly render input value
173+
//we need to check for this situation and simply return model value if we can't apply custom formatting
174+
candidateViewValue = parserResult.viewMapper(originalScope, locals);
175+
emptyViewValue = parserResult.viewMapper(originalScope, {});
176+
177+
return candidateViewValue!== emptyViewValue ? candidateViewValue : modelValue;
178+
}
160179
});
161180

162181
scope.select = function (activeIdx) {

0 commit comments

Comments
 (0)