From 4cdbb650b05eeea8a211e1ced1e155ae00114341 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Fri, 28 Oct 2016 22:51:41 +0200 Subject: [PATCH 1/2] feat(select): add the ability to pre-select the only option in the list * Adds the `md-select-only-option` attribute, that will cause `` to pre-select the first option, if it only has one option in it's list. * Fixes an ugly way of adding extra classes to the select container. * Removes a few variables and arguments that weren't being used. Fixes #9626. --- src/components/select/select.js | 33 +++++++++++++++++--------- src/components/select/select.spec.js | 35 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/src/components/select/select.js b/src/components/select/select.js index 3a9b028d183..d85a6590419 100755 --- a/src/components/select/select.js +++ b/src/components/select/select.js @@ -88,6 +88,8 @@ angular.module('material.components.select', [ * explicit label is present. * @param {string=} md-container-class Class list to get applied to the `.md-select-menu-container` * element (for custom styling). + * @param {string=} md-select-only-option If specified, a `` will automatically select + * it's first option, if it only has one. * * @usage * With a placeholder (label and aria-label are added dynamically) @@ -181,9 +183,6 @@ angular.module('material.components.select', [ */ function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $parse, $sce, $injector) { - var keyCodes = $mdConstant.KEY_CODE; - var NAVIGATION_KEYS = [keyCodes.SPACE, keyCodes.ENTER, keyCodes.UP_ARROW, keyCodes.DOWN_ARROW]; - return { restrict: 'E', require: ['^?mdInputContainer', 'mdSelect', 'ngModel', '?^form'], @@ -394,7 +393,7 @@ function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $ if (!isReadonly) { element - .on('focus', function(ev) { + .on('focus', function() { // Always focus the container (if we have one) so floating labels and other styles are // applied properly containerCtrl && containerCtrl.setFocused(true); @@ -550,12 +549,9 @@ function SelectDirective($mdSelect, $mdUtil, $mdConstant, $mdTheming, $mdAria, $ element[0].querySelector('.md-select-menu-container') ); selectScope = scope; - if (attr.mdContainerClass) { - var value = selectContainer[0].getAttribute('class') + ' ' + attr.mdContainerClass; - selectContainer[0].setAttribute('class', value); - } + attr.mdContainerClass && selectContainer.addClass(attr.mdContainerClass); selectMenuCtrl = selectContainer.find('md-select-menu').controller('mdSelectMenu'); - selectMenuCtrl.init(ngModelCtrl, attr.ngModel); + selectMenuCtrl.init(ngModelCtrl, attr); element.on('$destroy', function() { selectContainer.remove(); }); @@ -749,9 +745,9 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) { } }; - self.init = function(ngModel, binding) { + self.init = function(ngModel, parentAttrs) { self.ngModel = ngModel; - self.modelBinding = binding; + self.modelBinding = parentAttrs.ngModel; // Setup a more robust version of isEmpty to ensure value is a valid option self.ngModel.$isEmpty = function($viewValue) { @@ -782,6 +778,21 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) { }; } self.setMultiple(self.isMultiple); + + if (parentAttrs.hasOwnProperty('mdSelectOnlyOption')) { + $mdUtil.nextTick(function() { + var optionKeys = Object.keys(self.options); + + if (optionKeys.length === 1) { + var option = self.options[optionKeys[0]]; + + self.deselect(Object.keys(self.selected)[0]); + self.select(self.hashGetter(option.value), option.value); + self.refreshViewValue(); + self.ngModel.$setPristine(); + } + }, false); + } }; self.selectedLabels = function(opts) { diff --git a/src/components/select/select.spec.js b/src/components/select/select.spec.js index c6528b54d69..c73a7309f55 100755 --- a/src/components/select/select.spec.js +++ b/src/components/select/select.spec.js @@ -285,6 +285,41 @@ describe('', function() { expect($rootScope.testForm.defaultSelect.$error).toEqual({}); }); }); + + describe('mdSelectOnlyOption support', function() { + var $rootScope, $timeout; + + beforeEach(inject(function($injector) { + $rootScope = $injector.get('$rootScope'); + $timeout = $injector.get('$timeout'); + })); + + it('should select the first option if it only has one option', function() { + setupSelect('ng-model="val" md-select-only-option', [1]); + $timeout.flush(); + expect($rootScope.val).toBe(1); + }); + + it('should work with `multiple`', function() { + setupSelectMultiple('ng-model="val" md-select-only-option', [1]); + $timeout.flush(); + expect($rootScope.val).toEqual([1]); + }); + + it('should not do anything if there is more than one option', function() { + setupSelect('ng-model="val" md-select-only-option', [1, 2, 3]); + $timeout.flush(); + expect($rootScope.val).toBeUndefined(); + }); + + it('should keep the ngModel pristine', function() { + var el = setupSelect('ng-model="val" md-select-only-option', [1]); + var ngModel = el.find('md-select').controller('ngModel'); + + $timeout.flush(); + expect(ngModel.$pristine).toBe(true); + }); + }); }); describe('input container', function() { From 9643087784f9427762ab888e638cb7c830fcc7b1 Mon Sep 17 00:00:00 2001 From: Michael Prentice Date: Mon, 27 Apr 2020 20:32:08 -0400 Subject: [PATCH 2/2] fix(select): resolve merge issue --- src/components/select/select.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/select/select.js b/src/components/select/select.js index 0a20a68ac30..10a5c349ca7 100755 --- a/src/components/select/select.js +++ b/src/components/select/select.js @@ -893,7 +893,6 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) { } else { $element.find('md-content').removeAttr('aria-activedescendant'); } - self.setMultiple(self.isMultiple); }; /**