Skip to content
This repository has been archived by the owner on Aug 29, 2023. It is now read-only.

Commit

Permalink
fix(select): Fix duplicates in label. (#9695)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
topherfangio authored and kara committed Oct 12, 2016
1 parent 7706162 commit d553919
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
8 changes: 5 additions & 3 deletions src/components/select/select.js
Expand Up @@ -174,7 +174,7 @@ angular.module('material.components.select', [
* </div>
* </hljs>
*/
function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $compile, $parse) {
function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $parse) {
var keyCodes = $mdConstant.KEY_CODE;
var NAVIGATION_KEYS = [keyCodes.SPACE, keyCodes.ENTER, keyCodes.UP_ARROW, keyCodes.DOWN_ARROW];

Expand Down Expand Up @@ -408,7 +408,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $
}

scope.$watch(function() {
return selectMenuCtrl.selectedLabels();
return selectMenuCtrl.selectedLabels();
}, syncLabelText);

function syncLabelText() {
Expand Down Expand Up @@ -792,7 +792,9 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
} else if (mode == 'aria') {
mapFn = function(el) { return el.hasAttribute('aria-label') ? el.getAttribute('aria-label') : el.textContent; };
}
return selectedOptionEls.map(mapFn).join(', ');

// Ensure there are no duplicates; see https://github.com/angular/material/issues/9442
return $mdUtil.uniq(selectedOptionEls.map(mapFn)).join(', ');
} else {
return '';
}
Expand Down
19 changes: 19 additions & 0 deletions src/core/util/util.js
Expand Up @@ -833,6 +833,25 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in

return start + change * (-2 * tc + 3 * ts);
}
},

/**
* Provides an easy mechanism for removing duplicates from an array.
*
* var myArray = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
*
* $mdUtil.uniq(myArray) => [1, 2, 3, 4]
*
* @param {array} array The array whose unique values should be returned.
*
* @returns {array} A copy of the array containing only unique values.
*/
uniq: function(array) {
if (!array) { return; }

return array.filter(function(value, index, self) {
return self.indexOf(value) === index;
});
}
};

Expand Down
14 changes: 14 additions & 0 deletions src/core/util/util.spec.js
Expand Up @@ -717,4 +717,18 @@ describe('util', function() {
parent.remove();
});
});

describe('uniq', function() {
var $mdUtil;

beforeEach(inject(function(_$mdUtil_) {
$mdUtil = _$mdUtil_;
}));

it('returns a copy of the requested array with only unique values', function() {
var myArray = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];

expect($mdUtil.uniq(myArray)).toEqual([1, 2, 3, 4]);
});
});
});

0 comments on commit d553919

Please sign in to comment.