@@ -102,7 +102,8 @@ function MdCompilerProvider($compileProvider) {
102
102
* @name $mdCompilerProvider#respectPreAssignBindingsEnabled
103
103
*
104
104
* @param {boolean= } respected update the `respectPreAssignBindingsEnabled` state if provided,
105
- * otherwise just return the current Material `respectPreAssignBindingsEnabled` state.
105
+ * otherwise just return the current Material `respectPreAssignBindingsEnabled` state. Attempting
106
+ * to set this to `false` in AngularJS 1.7+ will throw an exception.
106
107
* @returns {boolean|MdCompilerProvider } current value if used as getter or itself (chaining)
107
108
* if used as setter
108
109
*
@@ -112,31 +113,45 @@ function MdCompilerProvider($compileProvider) {
112
113
* this doesn't affect directives/components created via regular AngularJS methods which
113
114
* constitute most Material and user-created components.
114
115
*
115
- * If disabled (`false`), the compiler assigns the value of each of the bindings to the
116
- * properties of the controller object before the constructor of this object is called.
116
+ * If disabled (`false`) and using an AngularJS version >= 1.5.10 and < 1.7.0, the compiler
117
+ * assigns the value of each of the bindings to the properties of the controller object before
118
+ * the constructor of this object is called.
117
119
*
118
120
* If enabled (`true`) the behavior depends on the AngularJS version used:
119
121
*
120
- * - `<1.5.10` - bindings are pre-assigned.
121
- * - `>=1.5.10 <1.7` - behaves like set to whatever `$compileProvider.preAssignBindingsEnabled()` reports.
122
- * If the `preAssignBindingsEnabled` flag wasn't set manually, it defaults to pre-assigning bindings
123
- * with AngularJS `1.5.x` and to calling the constructor first with AngularJS `1.6.x`.
124
- * - `>=1.7` - the compiler calls the constructor first before assigning bindings and
122
+ * - `<1.5.10`
123
+ * - Bindings are pre-assigned.
124
+ * - `>=1.5.10 <1.7`
125
+ * - Respects whatever `$compileProvider.preAssignBindingsEnabled()` reports. If the
126
+ * `preAssignBindingsEnabled` flag wasn't set manually, it defaults to pre-assigning bindings
127
+ * with AngularJS `1.5` and to calling the constructor first with AngularJS `1.6`.
128
+ * - `>=1.7`
129
+ * - The compiler calls the constructor first before assigning bindings and
125
130
* `$compileProvider.preAssignBindingsEnabled()` no longer exists.
126
131
*
127
- * The default value is `false` but will change to `true` in AngularJS Material 1.2.
132
+ * Defaults
133
+ * - The default value is `false` in AngularJS 1.6 and earlier.
134
+ * - It is planned to change this to default to `true` in AngularJS Material 1.2.
135
+ * - In AngularJS 1.7 and later, the value is always `true`. Trying to set the value to false will
136
+ * throw an exception.
128
137
*
129
- * It is recommended to set this flag to `true` in AngularJS Material 1.1.x. The only reason
130
- * it's not set that way by default is backwards compatibility. Not setting the flag to `true`
131
- * when AngularJS' `$compileProvider.preAssignBindingsEnabled()` is set to `false`
132
- * (i.e. default behavior in AngularJS 1.6 or newer) makes it hard to unit test
138
+ * It is recommended to set this flag to `true` when using AngularJS Material 1.1.x with
139
+ * AngularJS versions >= 1.5.10 and < 1.7.0. The only reason
140
+ * it's not set that way by default is backwards compatibility.
141
+ *
142
+ * By not setting the flag to `true` when AngularJS' `$compileProvider.preAssignBindingsEnabled()`
143
+ * is set to `false` (i.e. default behavior in AngularJS 1.6 or newer), unit testing of
133
144
* Material Dialog/Panel/Toast/BottomSheet controllers using the `$controller` helper
134
- * as it always follows the `$compileProvider.preAssignBindingsEnabled()` value.
145
+ * is problematic as it always follows AngularJS' `$compileProvider.preAssignBindingsEnabled()`
146
+ * value.
135
147
*/
136
- // TODO change it to `true` in Material 1.2.
137
- var respectPreAssignBindingsEnabled = false ;
148
+ var respectPreAssignBindingsEnabled = angular . version . major === 1 && angular . version . minor >= 7 ;
138
149
this . respectPreAssignBindingsEnabled = function ( respected ) {
139
150
if ( angular . isDefined ( respected ) ) {
151
+ if ( ! respected && angular . version . major === 1 && angular . version . minor >= 7 ) {
152
+ throw new Error (
153
+ 'Disabling respectPreAssignBindingsEnabled is not supported in AngularJS 1.7 or later.' ) ;
154
+ }
140
155
respectPreAssignBindingsEnabled = respected ;
141
156
return this ;
142
157
}
@@ -444,27 +459,36 @@ function MdCompilerProvider($compileProvider) {
444
459
445
460
/**
446
461
* Creates and instantiates a new controller with the specified options.
447
- * @param {!Object } options Options that include the controller
462
+ * @param {!Object } options Options that include the controller function or string.
448
463
* @param {!Object } injectLocals Locals to to be provided in the controller DI.
449
464
* @param {!Object } locals Locals to be injected to the controller.
450
465
* @returns {!Object } Created controller instance.
451
466
*/
452
467
MdCompilerService . prototype . _createController = function ( options , injectLocals , locals ) {
453
- // The third and fourth arguments to $controller are considered private and are undocumented:
454
- // https://github.com/angular/angular.js/blob/master/src/ng/controller.js#L86
455
- // Passing `true` as the third argument causes `$controller` to return a function that
456
- // gets the controller instance instead returning of the instance directly. When the
457
- // controller is defined as a function, `invokeCtrl.instance` is the *same instance* as
458
- // `invokeCtrl()`. However, then the controller is an ES6 class, `invokeCtrl.instance` is a
459
- // *different instance* from `invokeCtrl()`.
460
- var invokeCtrl = this . $controller ( options . controller , injectLocals , true , options . controllerAs ) ;
461
-
462
- if ( getPreAssignBindingsEnabled ( ) && options . bindToController ) {
463
- angular . extend ( invokeCtrl . instance , locals ) ;
468
+ var ctrl ;
469
+ if ( angular . version . major === 1 && angular . version . minor >= 7 ) {
470
+ ctrl = this . $controller ( options . controller , injectLocals ) ;
471
+ } else {
472
+ // The third argument to $controller is considered private and undocumented.
473
+ // Details: https://github.com/angular/angular.js/blob/v1.6.10/src/ng/controller.js#L102-L109
474
+ // Passing `true` as the third argument causes `$controller` to return a function that
475
+ // gets the controller instance instead of returning the instance directly. When the
476
+ // controller is defined as a function, `invokeCtrl.instance` is the *same instance* as
477
+ // `invokeCtrl()`. However, when the controller is an ES6 class, `invokeCtrl.instance` is a
478
+ // *different instance* from `invokeCtrl()`.
479
+ var invokeCtrl = this . $controller ( options . controller , injectLocals , true ) ;
480
+
481
+ if ( getPreAssignBindingsEnabled ( ) && options . bindToController ) {
482
+ angular . extend ( invokeCtrl . instance , locals ) ;
483
+ }
484
+
485
+ // Instantiate and initialize the specified controller.
486
+ ctrl = invokeCtrl ( ) ;
464
487
}
465
488
466
- // Instantiate and initialize the specified controller.
467
- var ctrl = invokeCtrl ( ) ;
489
+ if ( options . controllerAs ) {
490
+ injectLocals . $scope [ options . controllerAs ] = ctrl ;
491
+ }
468
492
469
493
if ( ! getPreAssignBindingsEnabled ( ) && options . bindToController ) {
470
494
angular . extend ( ctrl , locals ) ;
0 commit comments