diff --git a/src/components/select/demoBasicUsage/script.js b/src/components/select/demoBasicUsage/script.js index 32797f9299a..304b8d5e8f0 100755 --- a/src/components/select/demoBasicUsage/script.js +++ b/src/components/select/demoBasicUsage/script.js @@ -1,5 +1,3 @@ angular.module('selectDemoBasic', ['ngMaterial']) .controller('AppCtrl', function($scope) { - $scope.neighborhoods = ['Chelsea', 'Financial District', 'Midtown', 'West Village', 'Williamsburg']; - $scope.neighborhoods2 = ['Chelsea', 'Financial District', 'Lower Manhattan', 'Midtown', 'Soho', 'Upper Manhattan', 'West Village', 'Williamsburg' ]; }); diff --git a/src/components/select/select.js b/src/components/select/select.js index 3e2b93f3320..41a7dbf824f 100755 --- a/src/components/select/select.js +++ b/src/components/select/select.js @@ -14,7 +14,6 @@ - [ ] ng-model="foo" ng-model-options="{ trackBy: '$value.id' }" for objects - [ ] mdOption with value - [ ] Usage with input inside -- [ ] Usage with md-multiple ### TODO - POST RC1 ### - [ ] Abstract placement logic in $mdSelect service to $mdMenu service @@ -134,7 +133,6 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile, createSelect(); var originalRender = ngModel.$render; - ngModel.$render = function() { originalRender(); syncLabelText(); @@ -161,6 +159,31 @@ function SelectDirective($mdSelect, $mdUtil, $mdTheming, $interpolate, $compile, } } + var deregisterWatcher; + attr.$observe('ngMultiple', function(val) { + if (deregisterWatcher) deregisterWatcher(); + var parser = $parse(val); + deregisterWatcher = scope.$watch(function() { return parser(scope); }, function(multiple, prevVal) { + if (multiple === undefined && prevVal === undefined) return; // assume compiler did a good job + if (multiple) { + element.attr('multiple', 'multiple'); + } else { + element.removeAttr('multiple'); + } + if (selectContainer) { + var selectMenuCtrl = selectContainer.find('md-select-menu').controller('mdSelectMenu'); + selectMenuCtrl.setMultiple(multiple); + originalRender = ngModel.$render; + ngModel.$render = function() { + originalRender(); + syncLabelText(); + }; + selectMenuCtrl.refreshViewValue(); + ngModel.$render(); + } + }); + }); + attr.$observe('disabled', function(disabled) { if (typeof disabled == "string") { disabled = true; @@ -316,6 +339,33 @@ function SelectMenuDirective($parse, $mdUtil, $mdTheming) { // and values matching every option's controller. self.options = {}; + var deregisterCollectionWatch; + self.setMultiple = function(isMultiple) { + var ngModel = self.ngModel; + self.isMultiple = isMultiple; + if (deregisterCollectionWatch) deregisterCollectionWatch(); + + if (self.isMultiple) { + ngModel.$validators['md-multiple'] = validateArray; + ngModel.$render = renderMultiple; + + // watchCollection on the model because by default ngModel only watches the model's + // reference. This allowed the developer to also push and pop from their array. + $scope.$watchCollection($attrs.ngModel, function(value) { + if (validateArray(value)) renderMultiple(value); + }); + } else { + delete ngModel.$validators['md-multiple']; + ngModel.$render = renderSingular; + } + + function validateArray(modelValue, viewValue) { + // If a value is truthy but not an array, reject it. + // If value is undefined/falsy, accept that it's an empty array. + return angular.isArray(modelValue || viewValue || []); + } + }; + self.init = function(ngModel) { self.ngModel = ngModel; @@ -339,25 +389,7 @@ function SelectMenuDirective($parse, $mdUtil, $mdTheming) { return value; }; } - - if (self.isMultiple) { - ngModel.$validators['md-multiple'] = validateArray; - ngModel.$render = renderMultiple; - - // watchCollection on the model because by default ngModel only watches the model's - // reference. This allowed the developer to also push and pop from their array. - $scope.$watchCollection($attrs.ngModel, function(value) { - if (validateArray(value)) renderMultiple(value); - }); - } else { - ngModel.$render = renderSingular; - } - - function validateArray(modelValue, viewValue) { - // If a value is truthy but not an array, reject it. - // If value is undefined/falsy, accept that it's an empty array. - return angular.isArray(modelValue || viewValue || []); - } + self.setMultiple(self.isMultiple); }; self.selectedLabels = function() { @@ -694,19 +726,20 @@ function SelectProvider($$interimElementProvider) { focusOption('prev'); } - if (!selectCtrl.isMultiple) { - opts.selectEl.on('click', closeMenu); - opts.selectEl.on('keydown', function(e) { - if (e.keyCode == 32 || e.keyCode == 13) { - closeMenu(); - } - }); - } - function closeMenu() { - opts.restoreFocus = true; - scope.$evalAsync(function() { - $mdSelect.hide(selectCtrl.ngModel.$viewValue); - }); + opts.selectEl.on('click', checkCloseMenu); + opts.selectEl.on('keydown', function(e) { + if (e.keyCode == 32 || e.keyCode == 13) { + checkCloseMenu(); + } + }); + + function checkCloseMenu() { + if (!selectCtrl.isMultiple) { + opts.restoreFocus = true; + scope.$evalAsync(function() { + $mdSelect.hide(selectCtrl.ngModel.$viewValue); + }); + } } }