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

Commit 952a035

Browse files
Splaktarmmalerba
authored andcommitted
fix(select): edge case where the model value is unset w/ AngularJS 1.7.8 (#11724)
* fix(select): edge case where the model value is unset w/ AngularJS 1.7.8 when md-select is used inside of an AngularJS component - where the component sets an initial value - and that value is bound to the md-select's ng-model - and the options are using the value attribute (instead of ng-value) - and the md-select has ng-required that binds to an expression - and that expression is updated by $scope.$applyAsync in the component then the value could end up being reset to undefined. with this fix, the md-select's value remains set add an example of testing an AngularJS Component Fixes #11679 * build: update to AngularJS 1.7.8 clarify the package.json description
1 parent a5c11df commit 952a035

File tree

4 files changed

+81
-22
lines changed

4 files changed

+81
-22
lines changed

package-lock.json

Lines changed: 30 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "angular-material-source",
33
"version": "1.1.18",
4-
"description": "The AngularJS Material project is an implementation of Material Design in AngularJS. This project provides a set of reusable, well-tested, and accessible Material Design UI components. AngularJS Material is supported internally at Google by the AngularJS, Material Design UX and other product teams.",
4+
"description": "The AngularJS Material project is an implementation of Material Design in AngularJS. This project provides a set of reusable, well-tested, and accessible Material Design UI components. AngularJS Material is supported internally at Google by the AngularJS, Angular Components, and other product teams.",
55
"keywords": [
66
"client-side",
77
"browser",
@@ -35,14 +35,14 @@
3535
"@octokit/rest": "^15.9.2",
3636
"add-stream": "^1.0.0",
3737
"ajv": "^6.6.2",
38-
"angular": "^1.7.7",
39-
"angular-animate": "^1.7.7",
40-
"angular-aria": "^1.7.7",
41-
"angular-messages": "^1.7.7",
42-
"angular-mocks": "^1.7.7",
43-
"angular-route": "^1.7.7",
44-
"angular-sanitize": "^1.7.7",
45-
"angular-touch": "^1.7.7",
38+
"angular": "^1.7.8",
39+
"angular-animate": "^1.7.8",
40+
"angular-aria": "^1.7.8",
41+
"angular-messages": "^1.7.8",
42+
"angular-mocks": "^1.7.8",
43+
"angular-route": "^1.7.8",
44+
"angular-sanitize": "^1.7.8",
45+
"angular-touch": "^1.7.8",
4646
"angularytics": "^0.4.0",
4747
"canonical-path": "0.0.2",
4848
"cli-color": "^1.4.0",

src/components/select/select.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,8 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
839839
// the current option, which will be added, then we can be sure, that the validation
840840
// of the option has occurred before the option was added properly.
841841
// This means, that we have to manually trigger a new validation of the current option.
842-
if (angular.isDefined(self.ngModel.$modelValue) && self.hashGetter(self.ngModel.$modelValue) === hashKey) {
842+
if (angular.isDefined(self.ngModel.$$rawModelValue) &&
843+
self.hashGetter(self.ngModel.$$rawModelValue) === hashKey) {
843844
self.ngModel.$validate();
844845
}
845846

src/components/select/select.spec.js

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,28 @@ describe('<md-select>', function() {
22
var attachedElements = [];
33
var body, $document, $rootScope, $compile, $timeout, $material;
44

5+
/**
6+
* Register any custom components here.
7+
*/
8+
beforeEach(module(function ($compileProvider) {
9+
$compileProvider.component('requiredFormFieldComponent', {
10+
controller: ['$scope', function($scope) {
11+
var $ctrl = this;
12+
$ctrl.value = 'test';
13+
14+
$scope.$applyAsync(function () {
15+
$ctrl.required = true;
16+
});
17+
}],
18+
template: '<md-input-container><label>Test select</label>' +
19+
'<md-select name="value" ng-model="$ctrl.value" ng-required="$ctrl.required">' +
20+
'<md-option value="test">Test value</md-option>' +
21+
'</md-select></md-input-container>'
22+
});
23+
}));
24+
525
beforeEach(function() {
6-
module('material.components.select', 'material.components.input', 'ngSanitize');
26+
module('material.components.select', 'material.components.input', 'ngSanitize', 'ngMessages');
727

828
inject(function($injector) {
929
$document = $injector.get('$document');
@@ -1486,6 +1506,25 @@ describe('<md-select>', function() {
14861506
});
14871507
});
14881508

1509+
// Only test with custom components on AngularJS 1.5+
1510+
if (angular.version.major === 1 && angular.version.minor >= 5) {
1511+
describe('with custom components', function() {
1512+
it('should re-validate when the required value changes within $applyAsync', function() {
1513+
var nodes = $compile('<form name="testForm">' +
1514+
' <required-form-field-component></required-form-field-component>' +
1515+
'</form>')($rootScope);
1516+
var ctrl = nodes.find('required-form-field-component')
1517+
.controller('requiredFormFieldComponent');
1518+
1519+
$rootScope.$digest();
1520+
$timeout.flush();
1521+
1522+
expect(ctrl.value).toBe('test');
1523+
expect($rootScope.testForm.value.$error.required).toBeUndefined();
1524+
});
1525+
});
1526+
}
1527+
14891528
function setupSelect(attrs, options, skipLabel, scope, optCompileOpts) {
14901529
var el;
14911530
var template = '' +

0 commit comments

Comments
 (0)