@@ -94,15 +94,20 @@ var ngOptionsMinErr = minErr('ngOptions');
94
94
* * `label` **`for`** `value` **`in`** `array`
95
95
* * `select` **`as`** `label` **`for`** `value` **`in`** `array`
96
96
* * `label` **`group by`** `group` **`for`** `value` **`in`** `array`
97
+ * * `label` **`disable by`** `disable` **`for`** `value` **`in`** `array`
97
98
* * `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
99
+ * * `label` **`disable by`** `disable` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
98
100
* * `label` **`for`** `value` **`in`** `array` | orderBy:`orderexpr` **`track by`** `trackexpr`
99
101
* (for including a filter with `track by`)
100
102
* * for object data sources:
101
103
* * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
102
104
* * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
103
105
* * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
106
+ * * `label` **`disable by`** `disable` **`for (`**`key`**`,`** `value`**`) in`** `object`
104
107
* * `select` **`as`** `label` **`group by`** `group`
105
108
* **`for` `(`**`key`**`,`** `value`**`) in`** `object`
109
+ * * `select` **`as`** `label` **`disable by`** `disable`
110
+ * **`for` `(`**`key`**`,`** `value`**`) in`** `object`
106
111
*
107
112
* Where:
108
113
*
@@ -129,10 +134,10 @@ var ngOptionsMinErr = minErr('ngOptions');
129
134
.controller('ExampleController', ['$scope', function($scope) {
130
135
$scope.colors = [
131
136
{name:'black', shade:'dark'},
132
- {name:'white', shade:'light'},
137
+ {name:'white', shade:'light', notAnOption: true },
133
138
{name:'red', shade:'dark'},
134
- {name:'blue', shade:'dark'},
135
- {name:'yellow', shade:'light'}
139
+ {name:'blue', shade:'dark', notAnOption: true },
140
+ {name:'yellow', shade:'light', notAnOption: false }
136
141
];
137
142
$scope.myColor = $scope.colors[2]; // red
138
143
}]);
@@ -141,6 +146,7 @@ var ngOptionsMinErr = minErr('ngOptions');
141
146
<ul>
142
147
<li ng-repeat="color in colors">
143
148
Name: <input ng-model="color.name">
149
+ <input type="checkbox" ng-model="color.notAnOption"> Disabled?
144
150
[<a href ng-click="colors.splice($index, 1)">X</a>]
145
151
</li>
146
152
<li>
@@ -162,6 +168,12 @@ var ngOptionsMinErr = minErr('ngOptions');
162
168
<select ng-model="myColor" ng-options="color.name group by color.shade for color in colors">
163
169
</select><br/>
164
170
171
+ Color grouped by shade, with some disabled:
172
+ <select ng-model="myColor"
173
+ ng-options="color.name group by color.shade disable by color.notAnOption for color in colors">
174
+ </select><br/>
175
+
176
+
165
177
166
178
Select <a href ng-click="myColor = { name:'not in list', shade: 'other' }">bogus</a>.<br>
167
179
<hr/>
@@ -186,16 +198,17 @@ var ngOptionsMinErr = minErr('ngOptions');
186
198
*/
187
199
188
200
// jshint maxlen: false
189
- //000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
190
- var NG_OPTIONS_REGEXP = / ^ \s * ( [ \s \S ] + ?) (?: \s + a s \s + ( [ \s \S ] + ?) ) ? (?: \s + g r o u p \s + b y \s + ( [ \s \S ] + ?) ) ? \s + f o r \s + (?: ( [ \$ \w ] [ \$ \w ] * ) | (?: \( \s * ( [ \$ \w ] [ \$ \w ] * ) \s * , \s * ( [ \$ \w ] [ \$ \w ] * ) \s * \) ) ) \s + i n \s + ( [ \s \S ] + ?) (?: \s + t r a c k \s + b y \s + ( [ \s \S ] + ?) ) ? $ / ;
201
+ // //000011111111110000000000022222222220000000000000000000003333333333000000000000000000000004444444444400000000000005555555555555550000000006666666666666660000000777777777777777000000000000000888888888800000000000000000009999999999
202
+ var NG_OPTIONS_REGEXP = / ^ \s * ( [ \s \S ] + ?) (?: \s + a s \s + ( [ \s \S ] + ?) ) ? (?: \s + g r o u p \s + b y \s + ( [ \s \S ] + ?) ) ? (?: \s + d i s a b l e \s + b y \s + ( [ \s \S ] + ? ) ) ? \s + f o r \s + (?: ( [ \$ \w ] [ \$ \w ] * ) | (?: \( \s * ( [ \$ \w ] [ \$ \w ] * ) \s * , \s * ( [ \$ \w ] [ \$ \w ] * ) \s * \) ) ) \s + i n \s + ( [ \s \S ] + ?) (?: \s + t r a c k \s + b y \s + ( [ \s \S ] + ?) ) ? $ / ;
191
203
// 1: value expression (valueFn)
192
204
// 2: label expression (displayFn)
193
205
// 3: group by expression (groupByFn)
194
- // 4: array item variable name
195
- // 5: object item key variable name
196
- // 6: object item value variable name
197
- // 7: collection expression
198
- // 8: track by expression
206
+ // 4: disable by expression (disableByFn)
207
+ // 5: array item variable name
208
+ // 6: object item key variable name
209
+ // 7: object item value variable name
210
+ // 8: collection expression
211
+ // 9: track by expression
199
212
// jshint maxlen: 100
200
213
201
214
@@ -215,14 +228,14 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
215
228
// Extract the parts from the ngOptions expression
216
229
217
230
// The variable name for the value of the item in the collection
218
- var valueName = match [ 4 ] || match [ 6 ] ;
231
+ var valueName = match [ 5 ] || match [ 7 ] ;
219
232
// The variable name for the key of the item in the collection
220
- var keyName = match [ 5 ] ;
233
+ var keyName = match [ 6 ] ;
221
234
222
235
// An expression that generates the viewValue for an option if there is a label expression
223
236
var selectAs = / a s / . test ( match [ 0 ] ) && match [ 1 ] ;
224
237
// An expression that is used to track the id of each object in the options collection
225
- var trackBy = match [ 8 ] ;
238
+ var trackBy = match [ 9 ] ;
226
239
// An expression that generates the viewValue for an option if there is no label expression
227
240
var valueFn = $parse ( match [ 2 ] ? match [ 1 ] : valueName ) ;
228
241
var selectAsFn = selectAs && $parse ( selectAs ) ;
@@ -237,7 +250,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
237
250
function getHashOfValue ( viewValue ) { return hashKey ( viewValue ) ; } ;
238
251
var displayFn = $parse ( match [ 2 ] || match [ 1 ] ) ;
239
252
var groupByFn = $parse ( match [ 3 ] || '' ) ;
240
- var valuesFn = $parse ( match [ 7 ] ) ;
253
+ var disableByFn = $parse ( match [ 4 ] || '' ) ;
254
+ var valuesFn = $parse ( match [ 8 ] ) ;
241
255
242
256
var locals = { } ;
243
257
var getLocals = keyName ? function ( value , key ) {
@@ -250,11 +264,12 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
250
264
} ;
251
265
252
266
253
- function Option ( selectValue , viewValue , label , group ) {
267
+ function Option ( selectValue , viewValue , label , group , disabled ) {
254
268
this . selectValue = selectValue ;
255
269
this . viewValue = viewValue ;
256
270
this . label = label ;
257
271
this . group = group ;
272
+ this . disabled = disabled ;
258
273
}
259
274
260
275
return {
@@ -269,8 +284,10 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
269
284
var locals = getLocals ( values [ key ] , key ) ;
270
285
var label = displayFn ( scope , locals ) ;
271
286
var selectValue = getTrackByValue ( values [ key ] , locals ) ;
287
+ var disabledBy = disableByFn ( scope , locals ) ;
272
288
watchedArray . push ( selectValue ) ;
273
289
watchedArray . push ( label ) ;
290
+ watchedArray . push ( disabledBy ) ;
274
291
} ) ;
275
292
return watchedArray ;
276
293
} ) ,
@@ -296,7 +313,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
296
313
var selectValue = getTrackByValue ( viewValue , locals ) ;
297
314
var label = displayFn ( scope , locals ) ;
298
315
var group = groupByFn ( scope , locals ) ;
299
- var optionItem = new Option ( selectValue , viewValue , label , group ) ;
316
+ var disabled = disableByFn ( scope , locals ) ;
317
+ var optionItem = new Option ( selectValue , viewValue , label , group , disabled ) ;
300
318
301
319
optionItems . push ( optionItem ) ;
302
320
selectValueMap [ selectValue ] = optionItem ;
@@ -322,7 +340,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
322
340
return {
323
341
restrict : 'A' ,
324
342
terminal : true ,
325
- require : [ 'select' , '? ngModel' ] ,
343
+ require : [ 'select' , 'ngModel' ] ,
326
344
link : function ( scope , selectElement , attr , ctrls ) {
327
345
328
346
// if ngModel is not defined, we don't need to do anything
@@ -373,7 +391,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
373
391
selectCtrl . writeValue = function writeNgOptionsValue ( value ) {
374
392
var option = options . getOptionFromViewValue ( value ) ;
375
393
376
- if ( option ) {
394
+ if ( option && ! option . disabled ) {
377
395
if ( selectElement [ 0 ] . value !== option . selectValue ) {
378
396
removeUnknownOption ( ) ;
379
397
removeEmptyOption ( ) ;
@@ -397,7 +415,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
397
415
398
416
var selectedOption = options . selectValueMap [ selectElement . val ( ) ] ;
399
417
400
- if ( selectedOption ) {
418
+ if ( selectedOption && ! selectedOption . disabled ) {
401
419
removeEmptyOption ( ) ;
402
420
removeUnknownOption ( ) ;
403
421
return selectedOption . viewValue ;
@@ -422,18 +440,22 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
422
440
if ( value ) {
423
441
value . forEach ( function ( item ) {
424
442
var option = options . getOptionFromViewValue ( item ) ;
425
- if ( option ) option . element . selected = true ;
443
+ if ( option && ! option . disabled ) option . element . selected = true ;
426
444
} ) ;
427
445
}
428
446
} ;
429
447
430
448
431
449
selectCtrl . readValue = function readNgOptionsMultiple ( ) {
432
- var selectedValues = selectElement . val ( ) || [ ] ;
433
- return selectedValues . map ( function ( selectedKey ) {
434
- var option = options . selectValueMap [ selectedKey ] ;
435
- return option . viewValue ;
450
+ var selectedValues = selectElement . val ( ) || [ ] ,
451
+ selections = [ ] ;
452
+
453
+ forEach ( selectedValues , function ( value ) {
454
+ var option = options . selectValueMap [ value ] ;
455
+ if ( ! option . disabled ) selections . push ( option . viewValue ) ;
436
456
} ) ;
457
+
458
+ return selections ;
437
459
} ;
438
460
}
439
461
@@ -466,6 +488,7 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
466
488
467
489
function updateOptionElement ( option , element ) {
468
490
option . element = element ;
491
+ element . disabled = option . disabled ;
469
492
if ( option . value !== element . value ) element . value = option . selectValue ;
470
493
if ( option . label !== element . label ) {
471
494
element . label = option . label ;
0 commit comments