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

Commit d553919

Browse files
topherfangiokara
authored andcommitted
fix(select): Fix duplicates in label. (#9695)
Occasionally, `ng-repeat` appears to modify the DOM in such a way that it allows duplicates of selected items. When this happens, the `md-select` has issues displaying the proper label. Add a quick filter to ensure there are no duplicate selections in our labels. NOTE: I was unable to reproduce this in a spec; it appears to be related to the scope digets and never happens in the spec. I did update one of the demos to do some manual testing and ensure this fix works as expected, but it didn't have any real use inside of the demo so I removed it before submission. Fixes #9442.
1 parent 7706162 commit d553919

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

src/components/select/select.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ angular.module('material.components.select', [
174174
* </div>
175175
* </hljs>
176176
*/
177-
function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $compile, $parse) {
177+
function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $parse) {
178178
var keyCodes = $mdConstant.KEY_CODE;
179179
var NAVIGATION_KEYS = [keyCodes.SPACE, keyCodes.ENTER, keyCodes.UP_ARROW, keyCodes.DOWN_ARROW];
180180

@@ -408,7 +408,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $
408408
}
409409

410410
scope.$watch(function() {
411-
return selectMenuCtrl.selectedLabels();
411+
return selectMenuCtrl.selectedLabels();
412412
}, syncLabelText);
413413

414414
function syncLabelText() {
@@ -792,7 +792,9 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
792792
} else if (mode == 'aria') {
793793
mapFn = function(el) { return el.hasAttribute('aria-label') ? el.getAttribute('aria-label') : el.textContent; };
794794
}
795-
return selectedOptionEls.map(mapFn).join(', ');
795+
796+
// Ensure there are no duplicates; see https://github.com/angular/material/issues/9442
797+
return $mdUtil.uniq(selectedOptionEls.map(mapFn)).join(', ');
796798
} else {
797799
return '';
798800
}

src/core/util/util.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,25 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
833833

834834
return start + change * (-2 * tc + 3 * ts);
835835
}
836+
},
837+
838+
/**
839+
* Provides an easy mechanism for removing duplicates from an array.
840+
*
841+
* var myArray = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
842+
*
843+
* $mdUtil.uniq(myArray) => [1, 2, 3, 4]
844+
*
845+
* @param {array} array The array whose unique values should be returned.
846+
*
847+
* @returns {array} A copy of the array containing only unique values.
848+
*/
849+
uniq: function(array) {
850+
if (!array) { return; }
851+
852+
return array.filter(function(value, index, self) {
853+
return self.indexOf(value) === index;
854+
});
836855
}
837856
};
838857

src/core/util/util.spec.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,4 +717,18 @@ describe('util', function() {
717717
parent.remove();
718718
});
719719
});
720+
721+
describe('uniq', function() {
722+
var $mdUtil;
723+
724+
beforeEach(inject(function(_$mdUtil_) {
725+
$mdUtil = _$mdUtil_;
726+
}));
727+
728+
it('returns a copy of the requested array with only unique values', function() {
729+
var myArray = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
730+
731+
expect($mdUtil.uniq(myArray)).toEqual([1, 2, 3, 4]);
732+
});
733+
});
720734
});

0 commit comments

Comments
 (0)