@@ -61,6 +61,9 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
61
61
62
62
var focusFirst = originalScope . $eval ( attrs . typeaheadFocusFirst ) !== false ;
63
63
64
+ // a callback executed on initialization and on setting model value programatically, called with modelValue and should return item object or promise of it
65
+ var resolveItemCallback = attrs . typeaheadResolveItem ? $parse ( attrs . typeaheadResolveItem ) : undefined ;
66
+
64
67
//INTERNAL VARIABLES
65
68
66
69
//model setter executed upon match selection
@@ -172,6 +175,38 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
172
175
//we need to propagate user's query so we can higlight matches
173
176
scope . query = undefined ;
174
177
178
+ //we need last item to be available in formatters
179
+ scope . lastItem = undefined ;
180
+
181
+ //we need lastModel for sync checking last item
182
+ scope . lastModel = undefined ;
183
+
184
+ //resolve item, store it to lastItem and rerun modelCtrl formatters
185
+ var getItem = function ( modelValue ) {
186
+ if ( ! resolveItemCallback ) {
187
+ return ;
188
+ }
189
+ // call the callback
190
+ var itemCallbackResult = resolveItemCallback ( originalScope , { $model : modelValue } ) ;
191
+ // handle result
192
+ $q . when ( itemCallbackResult ) . then ( function ( item ) {
193
+ // discard results, if model value changed or another selection was made
194
+ if ( modelValue !== modelCtrl . $modelValue || modelValue !== scope . lastModel ) {
195
+ return ;
196
+ }
197
+
198
+ // store resolved item
199
+ scope . lastItem = item ;
200
+ // and rerun formatters
201
+ var viewValue = modelCtrl . $modelValue ;
202
+ for ( var i in modelCtrl . $formatters ) {
203
+ viewValue = modelCtrl . $formatters [ i ] ( viewValue ) ;
204
+ }
205
+ modelCtrl . $viewValue = viewValue ;
206
+ modelCtrl . $render ( ) ;
207
+ } ) ;
208
+ } ;
209
+
175
210
//Declare the timeout promise var outside the function scope so that stacked calls can be cancelled later
176
211
var timeoutPromise ;
177
212
@@ -228,6 +263,14 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
228
263
if ( inputFormatter ) {
229
264
230
265
locals . $model = modelValue ;
266
+ // if we have correct item, use it in formatter, otherwise, get it...
267
+ if ( modelValue === scope . lastModel ) {
268
+ locals . $item = scope . lastItem ;
269
+ } else {
270
+ scope . lastModel = modelValue ;
271
+ scope . lastItem = undefined ;
272
+ getItem ( modelValue ) ;
273
+ }
231
274
return inputFormatter ( originalScope , locals ) ;
232
275
233
276
} else {
@@ -248,8 +291,8 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap
248
291
var locals = { } ;
249
292
var model , item ;
250
293
251
- locals [ parserResult . itemName ] = item = scope . matches [ activeIdx ] . model ;
252
- model = parserResult . modelMapper ( originalScope , locals ) ;
294
+ locals [ parserResult . itemName ] = item = scope . lastItem = scope . matches [ activeIdx ] . model ;
295
+ model = scope . lastModel = parserResult . modelMapper ( originalScope , locals ) ;
253
296
$setModelValue ( originalScope , model ) ;
254
297
modelCtrl . $setValidity ( 'editable' , true ) ;
255
298
0 commit comments