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

Commit a73ab43

Browse files
devversionhansl
authored andcommitted
fix(ngModelCtrl) compatibility with snapshot breaking changes (#9685)
* AngularJS recently made a breaking API change which is is currently in Snapshot (angular/angular.js@87a2ff7) * This commit introduces a cross-version compatibility method to support the older and newer API.
1 parent 761493d commit a73ab43

File tree

4 files changed

+65
-4
lines changed

4 files changed

+65
-4
lines changed

src/components/datepicker/js/datepickerDirective.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@
422422
// Forwards any events from the input to the root element. This is necessary to get `updateOn`
423423
// working for events that don't bubble (e.g. 'blur') since Angular binds the handlers to
424424
// the `<md-datepicker>`.
425-
var updateOn = ngModelCtrl.$options && ngModelCtrl.$options.updateOn;
425+
var updateOn = self.$mdUtil.getModelOption(ngModelCtrl, 'updateOn');
426426

427427
if (updateOn) {
428428
this.ngInputElement.on(

src/components/select/select.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,11 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
734734

735735
// Allow users to provide `ng-model="foo" ng-model-options="{trackBy: 'foo.id'}"` so
736736
// that we can properly compare objects set on the model to the available options
737-
if (ngModel.$options && ngModel.$options.trackBy) {
737+
var trackByOption = $mdUtil.getModelOption(ngModel, 'trackBy');
738+
739+
if (trackByOption) {
738740
var trackByLocals = {};
739-
var trackByParsed = $parse(ngModel.$options.trackBy);
741+
var trackByParsed = $parse(trackByOption);
740742
self.hashGetter = function(value, valueScope) {
741743
trackByLocals.$value = value;
742744
return trackByParsed(valueScope || $scope, trackByLocals);
@@ -852,7 +854,7 @@ function SelectMenuDirective($parse, $mdUtil, $mdConstant, $mdTheming) {
852854
values.push(self.selected[hashKey]);
853855
}
854856
}
855-
var usingTrackBy = self.ngModel.$options && self.ngModel.$options.trackBy;
857+
var usingTrackBy = $mdUtil.getModelOption(self.ngModel, 'trackBy');
856858

857859
var newVal = self.isMultiple ? values : values[0];
858860
var prevVal = self.ngModel.$modelValue;

src/core/util/util.js

+19
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,25 @@ function UtilFactory($document, $timeout, $compile, $rootScope, $$mdAnimate, $in
6464
return new Date().getTime();
6565
},
6666

67+
/**
68+
* Cross-version compatibility method to retrieve an option of a ngModel controller,
69+
* which supports the breaking changes in the AngularJS snapshot (SHA 87a2ff76af5d0a9268d8eb84db5755077d27c84c).
70+
* @param {!angular.ngModelCtrl} ngModelCtrl
71+
* @param {!string} optionName
72+
* @returns {Object|undefined}
73+
*/
74+
getModelOption: function (ngModelCtrl, optionName) {
75+
if (!ngModelCtrl.$options) {
76+
return;
77+
}
78+
79+
var $options = ngModelCtrl.$options;
80+
81+
// The newer versions of Angular introduced a `getOption function and made the option values no longer
82+
// visible on the $options object.
83+
return $options.getOption ? $options.getOption(optionName) : $options[optionName]
84+
},
85+
6786
/**
6887
* Bi-directional accessor/mutator used to easily update an element's
6988
* property based on the current 'dir'ectional value.

src/core/util/util.spec.js

+40
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,46 @@ describe('util', function() {
6464

6565
});
6666

67+
describe('getModelOption', function() {
68+
69+
it('should support the old ngModelCtrl options', inject(function($mdUtil) {
70+
var ngModelCtrl = {
71+
$options: {
72+
trackBy: 'Test'
73+
}
74+
};
75+
76+
expect($mdUtil.getModelOption(ngModelCtrl, 'trackBy')).toBe('Test');
77+
}));
78+
79+
it('should support the newer ngModelCtrl options', inject(function($mdUtil) {
80+
var ngModelCtrl = {
81+
$options: {
82+
getOption: function() {
83+
return 'Test';
84+
}
85+
}
86+
};
87+
88+
expect($mdUtil.getModelOption(ngModelCtrl, 'trackBy')).toBe('Test');
89+
}));
90+
91+
it('should return nothing if $options is not set', inject(function($mdUtil) {
92+
expect($mdUtil.getModelOption({}, 'trackBy')).toBeFalsy();
93+
}));
94+
95+
it('should not throw if an option is not available', inject(function($mdUtil) {
96+
var ngModelCtrl = {
97+
$options: {}
98+
};
99+
100+
expect(function() {
101+
$mdUtil.getModelOption(ngModelCtrl, 'Unknown')
102+
}).not.toThrow();
103+
}));
104+
105+
});
106+
67107
describe('findFocusTarget', function() {
68108

69109
it('should not find valid focus target', inject(function($rootScope, $compile, $mdUtil) {

0 commit comments

Comments
 (0)