Actual Behavior:
What is the issue? *md-select showing multiple selections after updating option listWhat is the expected behavior? The md-select should have only one selectionCodePen (or steps to reproduce the issue): *
CodePen Demo which shows your issue: I have a codepen which attempts to reproduce this but I have not been able to at this time.Details:
Angular Versions: *
Angular Version: 1.5.8Angular Material Version: 1.1.1Additional Information:
Verified in IE 11 and Chrome 54.0.2840.59.
Troubleshooting Steps
Tracing the code in angular-material.js I stepped into the SelectMenuController's selectedLabels function and noted that selectedOptionEls.length would be 2 when this happened. I don't see how it could be 2, as the list is cleared and set fresh in my call to refresh the list.
vm.addCertificationType = function () {
CertificationTypeService.add(vm.newCertificationType).then(function (response) {
vm.newCertificationType = {};
getCertificationTypes();
$mdDialog.hide();
});
};
function getCertificationTypes() {
CertificationTypeService.getAll().then(function (response) {
if (vm.certificationTypes)
delete vm.certificationTypes;
vm.certificationTypes = response.data;
});
}
I inspect the DOM and there are no duplicate options when this is rendered, but at some point along the way, perhaps new items are being added to the DOM before the original ones are removed. I checked the network activity and there is only one call to retrieve the data. Just for the heck of it, I made two calls to getCertificationTypes and it showed 3 selected values but there were no dups in the list. Could this be some sort of priority issue where the ng-repeat must update the DOM before the selectedLabels() checks for options?
I've created a question on stackoverflow for this as well.
I've added a second call with $timeout for both calls in an effort to troubleshoot and an additional duplicate shows up in the selected value labels:
vm.addCertificationType = function () {
CertificationTypeService.add(vm.newCertificationType).then(function (response) {
vm.newCertificationType = {};
$timeout(getCertificationTypes, 1000);
$timeout(getCertificationTypes, 1000);
//getCertificationTypes();
$mdDialog.hide();
});
};

For one of the selects, I'm setting the selected value manually to the first object in the list. If I force the selection to happen in the next digest, it will resolve the issue for that md-select but the related md-selects are unpredictable.
function getCertificationTypes() {
CertificationTypeService.getAll().then(function (response) {
if (vm.certificationTypes)
delete vm.certificationTypes;
vm.certificationTypes = response.data;
vm.newSupplierCertification = {
certificationTypeId: vm.certificationTypes[0].id,
tempId: RandomService.guid()
};
var tmpNewSupplier = vm.newSupplierCertification;
vm.newSupplierCertification = {};
$timeout(function () {
vm.newSupplierCertification = tmpNewSupplier;
})
});
}

As you can see, the select label for all of them updates appropriately the first add but only the one where I am manually setting the select to the first item in the $timeout call above is updating appropriately for the successive calls.
If I manually add the item to the list and then sort the list afterwards then it works as expected, but this forces me to sort on the client. I believe it's acceptable to want to be able to replace the binding with an updated list without the above issue happening.
vm.addCertificationType = function () {
CertificationTypeService.add(vm.newCertificationType).then(function (response) {
vm.newCertificationType = {};
vm.certificationTypes.push(response.data);
vm.certificationTypes.sort(function (a, b) {
return a.name.localeCompare(b.name);
});
vm.newSupplierCertification = {
certificationTypeId: vm.certificationTypes[0].id,
tempId: RandomService.guid()
};
$mdDialog.hide();
});
};
Alternatively, if I add a track by to my md-option's ng-repeat then it works as well assumedly because there will never be duplicate items at any time in the DOM which would happen if completely replacing the list reference. My question is: why is the function to update the selected label being called before the duplicates are removed from the DOM?
<md-option ng-repeat="certificationType in addEditSupplierCtrl.certificationTypes track by certificationType.id" value="{{ certificationType.id }}">

Maybe the same as #9442?
This works for me, just added track by $index
<md-option ng-repeat="option in vm.options track by $index" ng-value="option.value">
@juanarbol didn't worked for me. I tracked by $index and by my custom id...same issue.
Any news about this one?
@nachogarrone Have you tried sort your custom ids before do ng-repeat?
I used "ng-if" if the list not null or empty. Then before binding data, set the list to null first, and assign the new list to object.
This may not be the best result, because it redraw the element (destroy and draw), but it works.
<md-select ng-if="theList!=null" >
<md-option ng-repeat="x in theList" value="x.id"> {{x.label}}</md-option>
</md-select>
Nothing of the above helped, tracking by $index, customId, ng-if...
Solution was to add ng-selected to md-option and check if it has the same value with ng-model.
```
ng-model="formData.unit"
required>
ng-repeat="(key, group) in formData.availableUnits">
ng-value="item"
ng-repeat="item in group">{{item}}
This seems to have been fixed (via https://github.com/angular/material/pull/9695) in 1.1.2.
There are some details on StackOverflow about how to work around this for earlier versions.
Most helpful comment
This works for me, just added
track by $index<md-option ng-repeat="option in vm.options track by $index" ng-value="option.value">