-
Notifications
You must be signed in to change notification settings - Fork 27.5k
feat($compile): isolate scope properties in controller context via controllerAs #7645
Conversation
@@ -1175,6 +1175,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | |||
var terminalPriority = -Number.MAX_VALUE, | |||
newScopeDirective, | |||
controllerDirectives = previousCompileContext.controllerDirectives, | |||
controllers, |
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.
having a separate object for this is suspect... I think elementControllers could probably be used
From our meeting today, it seems like we want to take the API in this direction: scope: {
"myData": "=someData",
"myString": "@someInterpolation",
"myExpr": "&someExpr"
},
bindToController: true,
controllerAs: "someCtrl" So you can either bind to |
What if I want bindings but don't need the scope to be isolate? E.g. it's needed to access controllers of the parent directives in the template. |
@thorn0 that's an anti-pattern. you should never be reaching out into a scope you don't own from components. isolate scopes were created specifically to isolate components from the context in which they are used. |
I understand this. However, consider a situation where directives are in a parent-child relationship so that they're already tightly coupled as children The Google guide says:
That's what I mean: one template, multiple controllers; so that both controllers, the parent's and the child's, can be accessed from the child's template. Of course, we can as well bind the parent controller to the children's scopes manually in each child directive definition, but it's not DRY. require: "^parentDirective",
link: function(scope, el, attrs, parent) {
scope.parent = parent;
} |
I forgot about this a while ago, but @lgalfaso reminded me of it, so I've added the |
Still has the changes to $injector though, which could be done without. |
otherwise, this looks good |
Right, it's been refactored so that $injector doesn't have a new method. |
PTAL @btford / @IgorMinar, I think this is probably good to land now. |
although @lgalfaso thinks there's a problem with it |
@caitp I was not aware of the restriction that you cannot have two directives with controllers under the same name at the same element. This restriction is already in place so I was not able to find anything wrong with the PR |
} | ||
|
||
return instance; | ||
}; | ||
|
||
function addIdentifier(locals, identifier, instance, name) { | ||
if (!(locals && typeof locals.$scope == 'object')) { |
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.
you can use isObject
here
new comments addressed |
PTAL --- Are we good to check this in for beta 18? |
@@ -878,7 +882,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | |||
: $compileNodes; | |||
|
|||
forEach(transcludeControllers, function(instance, name) { | |||
$linkNode.data('$' + name + 'Controller', instance); | |||
$linkNode.data('$' + name + 'Controller', instance.instance); |
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.
perhaps worth rewriting to eliminate the instance.instance
; controllerInstance.instance
maybe?
Thanks @caitp for submitting this 👍 would really love to see it released ASAP as it will allow us to use the great controller-as feature and help us to have a clean codebase. Please don't forget to merge it ;) |
lgtm |
…ntrollerAs It is now possible to ask the $compiler's isolate scope property machinery to reference properties by their isolate scope. The current syntax is to prefix the scope name with a '@', like so: scope: { "myData": "=someData", "myString": "@someInterpolation", "myExpr": "&someExpr" }, controllerAs: "someCtrl", bindtoController: true The putting of properties within the context of the controller will only occur if controllerAs is used for an isolate scope with the `bindToController` property of the directive definition object set to `true`. Closes angular#7635 Closes angular#7645
…ntrollerAs It is now possible to ask the $compiler's isolate scope property machinery to reference properties by their isolate scope. The current syntax is to prefix the scope name with a '@', like so: scope: { "myData": "=someData", "myString": "@someInterpolation", "myExpr": "&someExpr" }, controllerAs: "someCtrl", bindtoController: true The putting of properties within the context of the controller will only occur if controllerAs is used for an isolate scope with the `bindToController` property of the directive definition object set to `true`. Closes angular#7635 Closes angular#7645
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed.
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed.
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed.
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed.
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed.
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed. One difference with the previous implementation is that all non-ES2015-class controller instances were available on the element before calling their constructors. Now it depends on the relative order of controllers. Controller constructors shouldn't be used to access other controllers (e.g. via `$element.controller(directiveName)`). The recommended way is to use the `require` property of the directive definition object and the life cycle hooks `$onChanges` or `$onInit`. See https://docs.angularjs.org/api/ng/service/$compile#-require- https://docs.angularjs.org/api/ng/service/$compile#life-cycle-hooks
Now that we don't need to support `preAssignBindingsEnabled` (removed in angular#15782), complexity introduced in `$controller` by angular#7645 can be removed. One difference with the previous implementation is that all non-ES2015-class controller instances were available on the element before calling their constructors. Now it depends on the relative order of controllers. Controller constructors shouldn't be used to access other controllers (e.g. via `$element.controller(directiveName)`). The recommended way is to use the `require` property of the directive definition object and the life cycle hooks `$onChanges` or `$onInit`. See https://docs.angularjs.org/api/ng/service/$compile#-require- https://docs.angularjs.org/api/ng/service/$compile#life-cycle-hooks
Now that we don't need to support `preAssignBindingsEnabled` (removed in #15782), complexity introduced in `$controller` by #7645 can be removed. One difference with the previous implementation is that all non-ES2015-class controller instances were available on the element before calling their constructors. Now it depends on the relative order of controllers. Controller constructors shouldn't be used to access other controllers (e.g. via `$element.controller(directiveName)`). The recommended way is to use the `require` property of the directive definition object and the life cycle hooks `$onChanges` or `$onInit`. See https://docs.angularjs.org/api/ng/service/$compile#-require- https://docs.angularjs.org/api/ng/service/$compile#life-cycle-hooks Closes #16580
Now that we don't need to support `preAssignBindingsEnabled` (removed in #15782), complexity introduced in `$controller` by #7645 can be removed. One difference with the previous implementation is that all non-ES2015-class controller instances were available on the element before calling their constructors. Now it depends on the relative order of controllers. Controller constructors shouldn't be used to access other controllers (e.g. via `$element.controller(directiveName)`). The recommended way is to use the `require` property of the directive definition object and the life cycle hooks `$onChanges` or `$onInit`. See https://docs.angularjs.org/api/ng/service/$compile#-require- https://docs.angularjs.org/api/ng/service/$compile#life-cycle-hooks Closes #16580
It is now possible to ask the $compiler's isolate scope property machinery to
reference properties by their isolate scope.
The current syntax is to prefix the scope name with a '@', like so:
The putting of properties within the context of the controller will only occur
if controllerAs is used, and the @-prefix is kind of a gross sort of magic.
Benefits:
Problems:
Related to #7635