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

Commit 1e0dad1

Browse files
committed
handle all cases for multiple select
1 parent 3b392a1 commit 1e0dad1

File tree

2 files changed

+390
-62
lines changed

2 files changed

+390
-62
lines changed

src/ng/directive/select.js

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ var SelectController =
2323
['$element', '$scope', function($element, $scope) {
2424

2525
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
2729

2830
self.selectValueMap = {}; // Keys are the hashed values, values the original values
2931

3032
// If the ngModel doesn't get provided then provide a dummy noop version to prevent errors
3133
self.ngModelCtrl = noopNgModelController;
34+
self.multiple = false;
3235

3336
// The "unknown" option is one that is prepended to the list if the viewValue
3437
// does not match any of the options. When it is rendered the value of the unknown
@@ -63,8 +66,6 @@ var SelectController =
6366

6467
console.log('read', 'elval', val, 'possiblyhashed', realVal)
6568
if (self.hasOption(realVal)) {
66-
console.log('has selected val', realVal)
67-
// self.removeUnknownOption();
6869
return realVal;
6970
}
7071

@@ -75,7 +76,7 @@ var SelectController =
7576
// Write the value to the select control, the implementation of this changes depending
7677
// upon whether the select can have multiple values and whether ngOptions is at work.
7778
self.writeValue = function writeSingleValue(value) {
78-
console.log('write', value);
79+
console.log('write', value, 'hasOption', self.hasOption(value));
7980
if (self.hasOption(value)) {
8081
console.log('hasOption', value);
8182
self.removeUnknownOption();
@@ -141,10 +142,26 @@ var SelectController =
141142
return !!optionsMap.get(value);
142143
};
143144

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+
144162

145163
self.registerOption = function(optionScope, optionElement, optionAttrs, interpolateValueFn, interpolateTextFn) {
146164

147-
// console.log('attr', optionAttrs)
148165
if (optionAttrs.$attr.ngValue) {
149166
// The value attribute is set by ngValue
150167
var oldVal, hashedVal = NaN;
@@ -174,9 +191,8 @@ var SelectController =
174191
console.log('previouslySelected', previouslySelected, 'removal', removal)
175192

176193
if (removal && previouslySelected) {
177-
console.log('removed val is currently selected', $element.val())
178-
self.ngModelCtrl.$setViewValue(self.readValue());
179-
}
194+
updateModelAfterOptionChange();
195+
}
180196

181197
});
182198
} else if (interpolateValueFn) {
@@ -199,8 +215,8 @@ var SelectController =
199215
console.log('updated interpolated value', 'new', newVal, 'removed', removedVal, 'current', currentVal);
200216
if (removal && previouslySelected) {
201217
console.log('removed val is currently selected', $element.val())
202-
self.ngModelCtrl.$setViewValue(self.readValue());
203-
}
218+
updateModelAfterOptionChange();
219+
}
204220
});
205221
} else if (interpolateTextFn) {
206222
// The text content is interpolated
@@ -213,7 +229,7 @@ var SelectController =
213229
self.addOption(newVal, optionElement);
214230

215231
if (oldVal && previouslySelected) {
216-
self.ngModelCtrl.$setViewValue(self.readValue());
232+
updateModelAfterOptionChange();
217233
}
218234
});
219235
} else {
@@ -230,10 +246,17 @@ var SelectController =
230246

231247
if (newVal === 'true' || newVal && optionElement.prop('selected')) {
232248
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+
}
235256
oldDisabled = newVal;
236-
} else if (isDefined(oldDisabled) && !newVal || newVal === 'false') {
257+
}
258+
259+
// else if (isDefined(oldDisabled) && !newVal || newVal === 'false') {
237260
// var val = optionAttrs.value;
238261
// console.log('OA', optionAttrs.value);
239262
// var realVal = val in self.selectValueMap ? self.selectValueMap[val] : val;
@@ -243,21 +266,24 @@ var SelectController =
243266
// self.writeValue(realVal);
244267
// self.ngModelCtrl.$setViewValue(self.readValue());
245268
// }
246-
}
269+
// }
247270
});
248271

249272
optionElement.on('$destroy', function() {
250273
var currentValue = self.readValue();
251274
var removeValue = optionAttrs.value;
252275

253-
console.log('destroy', removeValue, 'elval', $element.val())
276+
console.log('destroy', 'removed', removeValue, 'elval', $element.val())
254277
// console.log('viewValue', self.ngModelCtrl.$viewValue)
255278
self.removeOption(removeValue);
256279
self.ngModelCtrl.$render();
257280

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) {
261287
self.ngModelCtrl.$setViewValue(self.readValue());
262288

263289
}
@@ -509,12 +535,14 @@ var selectDirective = function() {
509535
// we have to add an extra watch since ngModel doesn't work well with arrays - it
510536
// doesn't trigger rendering if only an item in the array changes.
511537
if (attr.multiple) {
538+
selectCtrl.multiple = true;
512539

513540
// Read value now needs to check each option to see if it is selected
514541
selectCtrl.readValue = function readMultipleValue() {
515542
var array = [];
516543
forEach(element.find('option'), function(option) {
517-
if (option.selected) {
544+
// console.log('read m o', option);
545+
if (option.selected && !option.disabled) {
518546
var val = option.value;
519547
array.push(val in selectCtrl.selectValueMap ? selectCtrl.selectValueMap[val] : val);
520548
}

0 commit comments

Comments
 (0)