-
Notifications
You must be signed in to change notification settings - Fork 3.4k
fix(compiler): respect preAssignBindingsEnabled state #10469
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,22 @@ | |
*/ | ||
angular | ||
.module('material.core') | ||
.service('$mdCompiler', MdCompilerService); | ||
.service('$mdCompiler', MdCompilerService) | ||
.provider('$$mdPreAssignBindings', PreAssignBindingsProvider); | ||
|
||
/** | ||
* Provider that is used to report the preAssignBindingsEnabled state to the $mdCompiler service. | ||
*/ | ||
function PreAssignBindingsProvider($compileProvider) { | ||
// To avoid that the preAssignBindings state causes issues when upgrading from AngularJS 1.5 to | ||
// AngularJS 1.6, AngularJS Material will only respect the preAssignBindingsEnabled state in 1.6 | ||
var respectPreAssignState = angular.version.major === 1 && angular.version.minor === 6; | ||
var fallbackValue = !!$compileProvider.preAssignBindingsEnabled; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As @mgol has pointed out, this will break in the future (most probably 1.7+). The plan is to remove the Base on what we have discussed in the last meeting, you need something like this: var defaultPreAssignValue = angular.version.major === 1 && angular.version.minor < 6;
var respectPreAssignState = angular.version.major === 1 && angular.version.minor > 5 &&
$compileProvider.preAssignBindingsEnabled;
this.$get = function() {
return respectPreAssingState ? $compileProvider.preAssignBindingsEnabled() : defaultPreAssignState;
}; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BTW, the current implementation will also break in 1.5.0-1.5.9 (where there is no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
How so? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
(To be clear, by "current implementation" I mean the implementation currently used in this PR.) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, I thought that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gkalpak Ah, you're right. @devversion The flag has been added in 1.5.9 which was released after a long wait and even after 1.6.0 was released. It's highly likely most of 1.5.x users will not have this flag available. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fallback value should be defined based on AngularJS version, not the presence of the Besides, as far as I understand, Material still supports AngularJS 1.3+, doesn't it? |
||
|
||
this.$get = function() { | ||
return respectPreAssignState ? $compileProvider.preAssignBindingsEnabled() : fallbackValue; | ||
}; | ||
} | ||
|
||
/** | ||
* @ngdoc service | ||
|
@@ -81,7 +96,9 @@ angular | |
* </hljs> | ||
* | ||
*/ | ||
function MdCompilerService($q, $templateRequest, $injector, $compile, $controller) { | ||
function MdCompilerService($q, $templateRequest, $injector, $compile, $controller, | ||
$$mdPreAssignBindings) { | ||
|
||
/** @private @const {!angular.$q} */ | ||
this.$q = $q; | ||
|
||
|
@@ -96,6 +113,9 @@ function MdCompilerService($q, $templateRequest, $injector, $compile, $controlle | |
|
||
/** @private @const {!angular.$controller} */ | ||
this.$controller = $controller; | ||
|
||
/** @private @const {boolean} */ | ||
this.preAssignBindingsEnabled = $$mdPreAssignBindings; | ||
} | ||
|
||
/** | ||
|
@@ -244,17 +264,12 @@ MdCompilerService.prototype._compileElement = function(locals, element, options) | |
// Instantiate controller if the developer provided one. | ||
if (options.controller) { | ||
|
||
var injectLocals = angular.extend(locals, { | ||
var injectLocals = angular.extend({}, locals, { | ||
$element: element | ||
}); | ||
|
||
var invokeCtrl = self.$controller(options.controller, injectLocals, true, options.controllerAs); | ||
|
||
if (options.bindToController) { | ||
angular.extend(invokeCtrl.instance, locals); | ||
} | ||
|
||
var ctrl = invokeCtrl(); | ||
// Create the specified controller instance. | ||
var ctrl = self._createController(options, injectLocals, locals); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In what way are those similar? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the way that |
||
|
||
// Unique identifier for Angular Route ngView controllers. | ||
element.data('$ngControllerController', ctrl); | ||
|
@@ -272,6 +287,34 @@ MdCompilerService.prototype._compileElement = function(locals, element, options) | |
|
||
}; | ||
|
||
/** | ||
* Creates and instantiates a new controller with the specified options. | ||
* @param {!Object} options Options that include the controller | ||
* @param {!Object} injectLocals Locals to to be provided in the controller DI. | ||
* @param {!Object} locals Locals to be injected to the controller. | ||
* @returns {!Object} Created controller instance. | ||
* @private | ||
*/ | ||
MdCompilerService.prototype._createController = function(options, injectLocals, locals) { | ||
var invokeCtrl = this.$controller(options.controller, injectLocals, true, options.controllerAs); | ||
|
||
if (this.preAssignBindingsEnabled && options.bindToController) { | ||
angular.extend(invokeCtrl.instance, locals); | ||
} | ||
|
||
// Instantiate and initialize the specified controller. | ||
var ctrl = invokeCtrl(); | ||
|
||
if (!this.preAssignBindingsEnabled && options.bindToController) { | ||
angular.extend(invokeCtrl.instance, locals); | ||
} | ||
|
||
// Call the $onInit hook if it's present on the controller. | ||
angular.isFunction(ctrl.$onInit) && ctrl.$onInit(); | ||
|
||
return ctrl; | ||
}; | ||
|
||
/** | ||
* Fetches an element removing it from the DOM and using it temporary for the compiler. | ||
* Elements which were fetched will be restored after use. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
About not respecting the flag in 1.5: it's about how
MdCompilerService#_createController
behaves so it will not break 1.5, it will just still preassign bindings in 1.5.10 even if the developer setspreAssignBindingsEnabled
tofalse
, I see it now.We could have respected the flag in 1.5.10 if your PR from a while ago accounting for this flag wasn't merged before this one as it wouldn't be breaking then - no one would be using 1.5.10 with Material & this flag set to
false
as this configuration was broken.I assume Material needs to ignore this flag because Material 1.1.3 works fine in 1.5.10 with this flag set to
false
? (Does it?)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, just in case we'd have to revert the removal and defer it to 1.8, it would be safer to check for
angular.version.minor > 5
instead ofangular.version.minor === 6
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, regarding the argument for not respecting the flag in
~1.5.10
but respecting in~1.6
- if someone was using Material with AngularJS 1.6 and it worked for them as the components they used worked fine, this change may break them.Maybe it would be safer to release this as 1.2.0, not 1.1.5 and then not ignoring the flag if it exists?
What do you think? @devversion @gkalpak @ThomasBurleson
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤢 True.
It sounds like there is indeed no (reaconable) way to make this non-breaking (without making it opt-in - e.g. with an
mdCompiler
flag) 😞