39
39
* * `select` **`as`** `label` **`for`** `value` **`in`** `array`
40
40
* * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
41
41
* * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array`
42
+ * * `label` **`for`** `value` **`in`** `array` **`compare`** `exp`
43
+ * * `select` **`as`** `label` **`for`** `value` **`in`** `array` **`compare`** `exp`
44
+ * * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`compare`** `exp`
45
+ * * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`compare`** `exp`
42
46
* * for object data sources:
43
47
* * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
44
48
* * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
45
49
* * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
46
50
* * `select` **`as`** `label` **`group by`** `group`
47
51
* **`for` `(`**`key`**`,`** `value`**`) in`** `object`
52
+ * * `label` **`for (`**`key` **`,`** `value`**`) in`** `object` **`compare`** `exp`
53
+ * * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object` **`compare`** `exp`
54
+ * * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object` **`compare`** `exp`
55
+ * * `select` **`as`** `label` **`group by`** `group`
56
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object` **`compare`** `exp`
48
57
*
49
58
* Where:
50
59
*
58
67
* element. If not specified, `select` expression will default to `value`.
59
68
* * `group`: The result of this expression will be used to group options using the `<optgroup>`
60
69
* DOM element.
70
+ * * `compare`: The result of this expression wil be used to compare models (instead of comparing object references) to
71
+ * choose the selected element
61
72
*
62
73
* @example
63
74
<doc:example>
122
133
123
134
var ngOptionsDirective = valueFn ( { terminal : true } ) ;
124
135
var selectDirective = [ '$compile' , '$parse' , function ( $compile , $parse ) {
125
- //00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777
126
- var NG_OPTIONS_REGEXP = / ^ \s * ( .* ?) (?: \s + a s \s + ( .* ?) ) ? (?: \s + g r o u p \s + b y \s + ( .* ) ) ? \s + f o r \s + (?: ( [ \$ \w ] [ \$ \w \d ] * ) | (?: \( \s * ( [ \$ \w ] [ \$ \w \d ] * ) \s * , \s * ( [ \$ \w ] [ \$ \w \d ] * ) \s * \) ) ) \s + i n \s + ( .* ) $ / ,
136
+ //0000111110000000000022220000000000000000000000333300000000000004444444444444444400000000055555555555555555000000066666666666666666000000000000000777700000000000000000888000
137
+ var NG_OPTIONS_REGEXP = / ^ \s * ( .* ?) (?: \s + a s \s + ( .* ?) ) ? (?: \s + g r o u p \s + b y \s + ( .* ) ) ? \s + f o r \s + (?: ( [ \$ \w ] [ \$ \w \d ] * ) | (?: \( \s * ( [ \$ \w ] [ \$ \w \d ] * ) \s * , \s * ( [ \$ \w ] [ \$ \w \d ] * ) \s * \) ) ) \s + i n \s + ( .* ? ) (?: \s + c o m p a r e \s + ( . * ? ) ) ? $ / ,
127
138
nullModelCtrl = { $setViewValue : noop } ;
128
139
129
140
return {
@@ -297,16 +308,17 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
297
308
298
309
if ( ! ( match = optionsExp . match ( NG_OPTIONS_REGEXP ) ) ) {
299
310
throw Error (
300
- "Expected ngOptions in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
311
+ "Expected ngOptionsq in form of '_select_ (as _label_)? for (_key_,)?_value_ in _collection_ (compare _comparison_)? '" +
301
312
" but got '" + optionsExp + "'." ) ;
302
313
}
303
-
314
+
304
315
var displayFn = $parse ( match [ 2 ] || match [ 1 ] ) ,
305
316
valueName = match [ 4 ] || match [ 6 ] ,
306
317
keyName = match [ 5 ] ,
307
318
groupByFn = $parse ( match [ 3 ] || '' ) ,
308
319
valueFn = $parse ( match [ 2 ] ? match [ 1 ] : valueName ) ,
309
320
valuesFn = $parse ( match [ 7 ] ) ,
321
+ compareFn = match [ 8 ] ? $parse ( match [ 8 ] ) : null ,
310
322
// This is an array of array of existing option groups in DOM. We try to reuse these if possible
311
323
// optionGroupsCache[0] is the options with no option group
312
324
// optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
@@ -390,10 +402,20 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
390
402
selectedSet = false , // nothing is selected yet
391
403
lastElement ,
392
404
element ,
393
- label ;
394
-
405
+ label ,
406
+ modelCompare = { } ;
407
+
395
408
if ( multiple ) {
396
- selectedSet = new HashMap ( modelValue ) ;
409
+ if ( compareFn ) {
410
+ var modelValueCompare = array ( ) ;
411
+ forEach ( modelValue , function ( key , value ) {
412
+ modelCompare [ valueName ] = modelValue [ key ] ;
413
+ modelValueCompare [ key ] = compareFn ( modelCompare ) ;
414
+ } ) ;
415
+ selectedSet = new HashMap ( modelValueCompare ) ;
416
+ } else {
417
+ selectedSet = new HashMap ( modelValue ) ;
418
+ }
397
419
} else if ( modelValue === null || nullOption ) {
398
420
// if we are not multiselect, and we are null then we have to add the nullOption
399
421
optionGroups [ '' ] . push ( { selected :modelValue === null , id :'' , label :'' } ) ;
@@ -409,9 +431,18 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
409
431
optionGroupNames . push ( optionGroupName ) ;
410
432
}
411
433
if ( multiple ) {
412
- selected = selectedSet . remove ( valueFn ( scope , locals ) ) != undefined ;
434
+ if ( compareFn ) {
435
+ selected = selectedSet . remove ( compareFn ( scope , locals ) ) != undefined ;
436
+ } else {
437
+ selected = selectedSet . remove ( valueFn ( scope , locals ) ) != undefined ;
438
+ }
413
439
} else {
414
- selected = modelValue === valueFn ( scope , locals ) ;
440
+ if ( compareFn ) {
441
+ modelCompare [ valueName ] = modelValue ;
442
+ selected = compareFn ( scope , locals ) === compareFn ( modelCompare ) ;
443
+ } else {
444
+ selected = modelValue === valueFn ( scope , locals ) ;
445
+ }
415
446
selectedSet = selectedSet || selected ; // see if at least one item is selected
416
447
}
417
448
label = displayFn ( scope , locals ) ; // what will be seen by the user
0 commit comments