Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit c1441e3

Browse files
feat(select) : allow compariong objects using an expression
Add to ng-options the possibility to select option using an expression (instead of comparing by reference)
1 parent 9a3f038 commit c1441e3

File tree

2 files changed

+61
-9
lines changed

2 files changed

+61
-9
lines changed

src/ng/directive/select.js

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,21 @@
3939
* * `select` **`as`** `label` **`for`** `value` **`in`** `array`
4040
* * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
4141
* * `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`
4246
* * for object data sources:
4347
* * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
4448
* * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
4549
* * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
4650
* * `select` **`as`** `label` **`group by`** `group`
4751
* **`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`
4857
*
4958
* Where:
5059
*
@@ -58,6 +67,8 @@
5867
* element. If not specified, `select` expression will default to `value`.
5968
* * `group`: The result of this expression will be used to group options using the `<optgroup>`
6069
* 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
6172
*
6273
* @example
6374
<doc:example>
@@ -122,8 +133,8 @@
122133

123134
var ngOptionsDirective = valueFn({ terminal: true });
124135
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
125-
//00001111100000000000222200000000000000000000003333000000000000044444444444444444000000000555555555555555550000000666666666666666660000000000000007777
126-
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*)$/,
136+
//0000111110000000000022220000000000000000000000333300000000000004444444444444444400000000055555555555555555000000066666666666666666000000000000000777700000000000000000888000
137+
var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*?)(?:\s+compare\s+(.*?))?$/,
127138
nullModelCtrl = {$setViewValue: noop};
128139

129140
return {
@@ -297,16 +308,17 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
297308

298309
if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {
299310
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_)?'" +
301312
" but got '" + optionsExp + "'.");
302313
}
303-
314+
304315
var displayFn = $parse(match[2] || match[1]),
305316
valueName = match[4] || match[6],
306317
keyName = match[5],
307318
groupByFn = $parse(match[3] || ''),
308319
valueFn = $parse(match[2] ? match[1] : valueName),
309320
valuesFn = $parse(match[7]),
321+
compareFn = match[8] ? $parse(match[8]) : null,
310322
// This is an array of array of existing option groups in DOM. We try to reuse these if possible
311323
// optionGroupsCache[0] is the options with no option group
312324
// optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
@@ -390,10 +402,20 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
390402
selectedSet = false, // nothing is selected yet
391403
lastElement,
392404
element,
393-
label;
394-
405+
label,
406+
modelCompare = {};
407+
395408
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+
}
397419
} else if (modelValue === null || nullOption) {
398420
// if we are not multiselect, and we are null then we have to add the nullOption
399421
optionGroups[''].push({selected:modelValue === null, id:'', label:''});
@@ -409,9 +431,18 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
409431
optionGroupNames.push(optionGroupName);
410432
}
411433
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+
}
413439
} 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+
}
415446
selectedSet = selectedSet || selected; // see if at least one item is selected
416447
}
417448
label = displayFn(scope, locals); // what will be seen by the user

test/ng/directive/selectSpec.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,27 @@ describe('select', function() {
794794
expect(element.val()).toEqual('blue');
795795
});
796796

797+
describe('compare', function() {
798+
if('should select the good object using compare expression', function() {
799+
createSelect({
800+
'ng-model': 'selected',
801+
'ng-options': 'value.id as value.name for value in values compare value.id'
802+
});
803+
804+
scope.$apply(function() {
805+
scope.values = [{id: 10, name: 'A'}, {id: 20, name: 'B'}, {id: 30, name: 'C'}];
806+
scope.selected = {id: 20, name: 'B'};
807+
});
808+
809+
expect(element.val()).toEqual(20);
810+
811+
scope.$apply(function() {
812+
scope.selected = {id: 30, name: 'C'};
813+
});
814+
815+
expect(element.val()).toEqual(30);
816+
});
817+
});
797818

798819
it('should bind to object value', function() {
799820
createSelect({

0 commit comments

Comments
 (0)