@@ -23,12 +23,15 @@ var SelectController =
23
23
[ '$element' , '$scope' , function ( $element , $scope ) {
24
24
25
25
var self = this ,
26
- optionsMap = new HashMap ( ) ;
26
+ optionsMap = new HashMap ( ) ,
27
+ handleMultipleDestroy = false ; // Flag to run an update to the model after selected options
28
+ // in a multiple select have been destroyed
27
29
28
30
self . selectValueMap = { } ; // Keys are the hashed values, values the original values
29
31
30
32
// If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
31
33
self . ngModelCtrl = noopNgModelController ;
34
+ self . multiple = false ;
32
35
33
36
// The "unknown" option is one that is prepended to the list if the viewValue
34
37
// does not match any of the options. When it is rendered the value of the unknown
@@ -63,8 +66,6 @@ var SelectController =
63
66
64
67
console . log ( 'read' , 'elval' , val , 'possiblyhashed' , realVal )
65
68
if ( self . hasOption ( realVal ) ) {
66
- console . log ( 'has selected val' , realVal )
67
- // self.removeUnknownOption();
68
69
return realVal ;
69
70
}
70
71
@@ -75,7 +76,7 @@ var SelectController =
75
76
// Write the value to the select control, the implementation of this changes depending
76
77
// upon whether the select can have multiple values and whether ngOptions is at work.
77
78
self . writeValue = function writeSingleValue ( value ) {
78
- console . log ( 'write' , value ) ;
79
+ console . log ( 'write' , value , 'hasOption' , self . hasOption ( value ) ) ;
79
80
if ( self . hasOption ( value ) ) {
80
81
console . log ( 'hasOption' , value ) ;
81
82
self . removeUnknownOption ( ) ;
@@ -141,10 +142,26 @@ var SelectController =
141
142
return ! ! optionsMap . get ( value ) ;
142
143
} ;
143
144
145
+ var handleMultipleChanges = false ;
146
+ function updateModelAfterOptionChange ( renderAfter ) {
147
+ if ( self . multiple ) {
148
+ if ( ! handleMultipleChanges ) {
149
+ handleMultipleChanges = true ;
150
+ } else {
151
+ $scope . $$postDigest ( function ( ) {
152
+ handleMultipleChanges = false ;
153
+ self . ngModelCtrl . $setViewValue ( self . readValue ( ) ) ;
154
+ if ( renderAfter ) self . ngModelCtrl . $render ( ) ;
155
+ } ) ;
156
+ }
157
+ } else {
158
+ self . ngModelCtrl . $setViewValue ( self . readValue ( ) ) ;
159
+ }
160
+ }
161
+
144
162
145
163
self . registerOption = function ( optionScope , optionElement , optionAttrs , interpolateValueFn , interpolateTextFn ) {
146
164
147
- // console.log('attr', optionAttrs)
148
165
if ( optionAttrs . $attr . ngValue ) {
149
166
// The value attribute is set by ngValue
150
167
var oldVal , hashedVal = NaN ;
@@ -174,9 +191,8 @@ var SelectController =
174
191
console . log ( 'previouslySelected' , previouslySelected , 'removal' , removal )
175
192
176
193
if ( removal && previouslySelected ) {
177
- console . log ( 'removed val is currently selected' , $element . val ( ) )
178
- self . ngModelCtrl . $setViewValue ( self . readValue ( ) ) ;
179
- }
194
+ updateModelAfterOptionChange ( ) ;
195
+ }
180
196
181
197
} ) ;
182
198
} else if ( interpolateValueFn ) {
@@ -199,8 +215,8 @@ var SelectController =
199
215
console . log ( 'updated interpolated value' , 'new' , newVal , 'removed' , removedVal , 'current' , currentVal ) ;
200
216
if ( removal && previouslySelected ) {
201
217
console . log ( 'removed val is currently selected' , $element . val ( ) )
202
- self . ngModelCtrl . $setViewValue ( self . readValue ( ) ) ;
203
- }
218
+ updateModelAfterOptionChange ( ) ;
219
+ }
204
220
} ) ;
205
221
} else if ( interpolateTextFn ) {
206
222
// The text content is interpolated
@@ -213,7 +229,7 @@ var SelectController =
213
229
self . addOption ( newVal , optionElement ) ;
214
230
215
231
if ( oldVal && previouslySelected ) {
216
- self . ngModelCtrl . $setViewValue ( self . readValue ( ) ) ;
232
+ updateModelAfterOptionChange ( ) ;
217
233
}
218
234
} ) ;
219
235
} else {
@@ -230,10 +246,17 @@ var SelectController =
230
246
231
247
if ( newVal === 'true' || newVal && optionElement . prop ( 'selected' ) ) {
232
248
console . log ( 'disabled' )
233
- self . ngModelCtrl . $setViewValue ( null ) ;
234
- self . ngModelCtrl . $render ( ) ;
249
+
250
+ if ( self . multiple ) {
251
+ updateModelAfterOptionChange ( true ) ;
252
+ } else {
253
+ self . ngModelCtrl . $setViewValue ( null ) ;
254
+ self . ngModelCtrl . $render ( ) ;
255
+ }
235
256
oldDisabled = newVal ;
236
- } else if ( isDefined ( oldDisabled ) && ! newVal || newVal === 'false' ) {
257
+ }
258
+
259
+ // else if (isDefined(oldDisabled) && !newVal || newVal === 'false') {
237
260
// var val = optionAttrs.value;
238
261
// console.log('OA', optionAttrs.value);
239
262
// var realVal = val in self.selectValueMap ? self.selectValueMap[val] : val;
@@ -243,21 +266,24 @@ var SelectController =
243
266
// self.writeValue(realVal);
244
267
// self.ngModelCtrl.$setViewValue(self.readValue());
245
268
// }
246
- }
269
+ // }
247
270
} ) ;
248
271
249
272
optionElement . on ( '$destroy' , function ( ) {
250
273
var currentValue = self . readValue ( ) ;
251
274
var removeValue = optionAttrs . value ;
252
275
253
- console . log ( 'destroy' , removeValue , 'elval' , $element . val ( ) )
276
+ console . log ( 'destroy' , 'removed' , removeValue , 'elval' , $element . val ( ) )
254
277
// console.log('viewValue', self.ngModelCtrl.$viewValue)
255
278
self . removeOption ( removeValue ) ;
256
279
self . ngModelCtrl . $render ( ) ;
257
280
258
- if ( currentValue === removeValue ) {
259
- // console.log('removed val is currently selected', $element.val())
260
- // console.log('self.readValue()', self.readValue());
281
+ if ( self . multiple && currentValue && currentValue . indexOf ( removeValue ) !== - 1 ) {
282
+ // When multiple (selected) options are destroyed at the same time, we don't want
283
+ // to run a model update for each of them. Instead, run a single update in the $$postDigest
284
+ // NOTE: Will that interfere with the regular model update?
285
+ updateModelAfterOptionChange ( ) ;
286
+ } else if ( currentValue === removeValue ) {
261
287
self . ngModelCtrl . $setViewValue ( self . readValue ( ) ) ;
262
288
263
289
}
@@ -509,12 +535,14 @@ var selectDirective = function() {
509
535
// we have to add an extra watch since ngModel doesn't work well with arrays - it
510
536
// doesn't trigger rendering if only an item in the array changes.
511
537
if ( attr . multiple ) {
538
+ selectCtrl . multiple = true ;
512
539
513
540
// Read value now needs to check each option to see if it is selected
514
541
selectCtrl . readValue = function readMultipleValue ( ) {
515
542
var array = [ ] ;
516
543
forEach ( element . find ( 'option' ) , function ( option ) {
517
- if ( option . selected ) {
544
+ // console.log('read m o', option);
545
+ if ( option . selected && ! option . disabled ) {
518
546
var val = option . value ;
519
547
array . push ( val in selectCtrl . selectValueMap ? selectCtrl . selectValueMap [ val ] : val ) ;
520
548
}
0 commit comments