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

Commit aab8001

Browse files
committed
handle all cases for multiple select
1 parent 6d29b21 commit aab8001

File tree

2 files changed

+390
-62
lines changed

2 files changed

+390
-62
lines changed

src/ng/directive/select.js

+48-20
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@ var SelectController =
1414
['$element', '$scope', function($element, $scope) {
1515

1616
var self = this,
17-
optionsMap = new HashMap();
17+
optionsMap = new HashMap(),
18+
handleMultipleDestroy = false; // Flag to run an update to the model after selected options
19+
// in a multiple select have been destroyed
1820

1921
self.selectValueMap = {}; // Keys are the hashed values, values the original values
2022

2123
// If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
2224
self.ngModelCtrl = noopNgModelController;
25+
self.multiple = false;
2326

2427
// The "unknown" option is one that is prepended to the list if the viewValue
2528
// does not match any of the options. When it is rendered the value of the unknown
@@ -54,8 +57,6 @@ var SelectController =
5457

5558
console.log('read', 'elval', val, 'possiblyhashed', realVal)
5659
if (self.hasOption(realVal)) {
57-
console.log('has selected val', realVal)
58-
// self.removeUnknownOption();
5960
return realVal;
6061
}
6162

@@ -66,7 +67,7 @@ var SelectController =
6667
// Write the value to the select control, the implementation of this changes depending
6768
// upon whether the select can have multiple values and whether ngOptions is at work.
6869
self.writeValue = function writeSingleValue(value) {
69-
console.log('write', value);
70+
console.log('write', value, 'hasOption', self.hasOption(value));
7071
if (self.hasOption(value)) {
7172
console.log('hasOption', value);
7273
self.removeUnknownOption();
@@ -131,10 +132,26 @@ var SelectController =
131132
return !!optionsMap.get(value);
132133
};
133134

135+
var handleMultipleChanges = false;
136+
function updateModelAfterOptionChange(renderAfter) {
137+
if (self.multiple) {
138+
if (!handleMultipleChanges) {
139+
handleMultipleChanges = true;
140+
} else {
141+
$scope.$$postDigest(function() {
142+
handleMultipleChanges = false;
143+
self.ngModelCtrl.$setViewValue(self.readValue());
144+
if (renderAfter) self.ngModelCtrl.$render();
145+
});
146+
}
147+
} else {
148+
self.ngModelCtrl.$setViewValue(self.readValue());
149+
}
150+
}
151+
134152

135153
self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
136154

137-
// console.log('attr', optionAttrs)
138155
if (optionAttrs.$attr.ngValue) {
139156
// The value attribute is set by ngValue
140157
var oldVal, hashedVal = NaN;
@@ -164,9 +181,8 @@ var SelectController =
164181
console.log('previouslySelected', previouslySelected, 'removal', removal)
165182

166183
if (removal && previouslySelected) {
167-
console.log('removed val is currently selected', $element.val())
168-
self.ngModelCtrl.$setViewValue(self.readValue());
169-
}
184+
updateModelAfterOptionChange();
185+
}
170186

171187
});
172188
} else if (interpolateValueFn) {
@@ -189,8 +205,8 @@ var SelectController =
189205
console.log('updated interpolated value', 'new', newVal, 'removed', removedVal, 'current', currentVal);
190206
if (removal && previouslySelected) {
191207
console.log('removed val is currently selected', $element.val())
192-
self.ngModelCtrl.$setViewValue(self.readValue());
193-
}
208+
updateModelAfterOptionChange();
209+
}
194210
});
195211
} else if (interpolateTextFn) {
196212
// The text content is interpolated
@@ -203,7 +219,7 @@ var SelectController =
203219
self.addOption(newVal, optionElement);
204220

205221
if (oldVal && previouslySelected) {
206-
self.ngModelCtrl.$setViewValue(self.readValue());
222+
updateModelAfterOptionChange();
207223
}
208224
});
209225
} else {
@@ -220,10 +236,17 @@ var SelectController =
220236

221237
if (newVal === 'true' || newVal && optionElement.prop('selected')) {
222238
console.log('disabled')
223-
self.ngModelCtrl.$setViewValue(null);
224-
self.ngModelCtrl.$render();
239+
240+
if (self.multiple) {
241+
updateModelAfterOptionChange(true);
242+
} else {
243+
self.ngModelCtrl.$setViewValue(null);
244+
self.ngModelCtrl.$render();
245+
}
225246
oldDisabled = newVal;
226-
} else if (isDefined(oldDisabled) && !newVal || newVal === 'false') {
247+
}
248+
249+
// else if (isDefined(oldDisabled) && !newVal || newVal === 'false') {
227250
// var val = optionAttrs.value;
228251
// console.log('OA', optionAttrs.value);
229252
// var realVal = val in self.selectValueMap ? self.selectValueMap[val] : val;
@@ -233,21 +256,24 @@ var SelectController =
233256
// self.writeValue(realVal);
234257
// self.ngModelCtrl.$setViewValue(self.readValue());
235258
// }
236-
}
259+
// }
237260
});
238261

239262
optionElement.on('$destroy', function() {
240263
var currentValue = self.readValue();
241264
var removeValue = optionAttrs.value;
242265

243-
console.log('destroy', removeValue, 'elval', $element.val())
266+
console.log('destroy', 'removed', removeValue, 'elval', $element.val())
244267
// console.log('viewValue', self.ngModelCtrl.$viewValue)
245268
self.removeOption(removeValue);
246269
self.ngModelCtrl.$render();
247270

248-
if (currentValue === removeValue) {
249-
// console.log('removed val is currently selected', $element.val())
250-
// console.log('self.readValue()', self.readValue());
271+
if (self.multiple && currentValue && currentValue.indexOf(removeValue) !== -1) {
272+
// When multiple (selected) options are destroyed at the same time, we don't want
273+
// to run a model update for each of them. Instead, run a single update in the $$postDigest
274+
// NOTE: Will that interfere with the regular model update?
275+
updateModelAfterOptionChange();
276+
} else if (currentValue === removeValue) {
251277
self.ngModelCtrl.$setViewValue(self.readValue());
252278

253279
}
@@ -499,12 +525,14 @@ var selectDirective = function() {
499525
// we have to add an extra watch since ngModel doesn't work well with arrays - it
500526
// doesn't trigger rendering if only an item in the array changes.
501527
if (attr.multiple) {
528+
selectCtrl.multiple = true;
502529

503530
// Read value now needs to check each option to see if it is selected
504531
selectCtrl.readValue = function readMultipleValue() {
505532
var array = [];
506533
forEach(element.find('option'), function(option) {
507-
if (option.selected) {
534+
// console.log('read m o', option);
535+
if (option.selected && !option.disabled) {
508536
var val = option.value;
509537
array.push(val in selectCtrl.selectValueMap ? selectCtrl.selectValueMap[val] : val);
510538
}

0 commit comments

Comments
 (0)