-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Component tree: controller bindToParent? #14060
Comments
I think it would be nice to have something equivalent to ng2's In the meantime, you could query your children (e.g. in the post-linking phase or when needed) and access their controllers. (If Here is a hacky demo of what you can do today. |
What about #14080 ? <user-crud> // $crud controller
<user-list as="$crud.users" users="$crud.users" on-select="$ctrl.editUser"></user-list>
<user-editor as="$crud.editor" user="$crud.user" on-save="$ctrl.saveUser"></user-editor>
</user-crud> And at the same time, you can reuse Ops, and there is other inconvenience for bindToParent: it is polluting parent directive controller, so, you need to use it carefully or you may overwrite things. Ops, an inconvenience for using $element.find() is you have to be sure that none of your children and children-children-... would have the directive that are you looking for, find just looks for all instances in the whole children tree. Uhmm I do not know for sure how it is working in ng2. By the way, from what I understand from the template, you are using on-select/on-save without <user-crud> // $crud controller
<user-list as="$crud.users" users="$crud.users" on-select="$ctrl.editUser(user)"></user-list>
<user-editor as="$crud.editor" user="$crud.user" on-save="$ctrl.saveUser($crud.user)"></user-editor>
</user-crud> It should be nicer. You should do something like this in your component definition: module.component('userList', {
...
bindings : {
fireSelect: '&onSelect',// notify changes with $ctrl.fireSelect({user: currentUser})
...
},
...
}); |
Thank you for the updates. I've been working with this, and tried the approach @gkalpak suggested. It's a fact that we can use $element to find the child controllers and bind them. It works pretty well, but it still have some problems: First that we need to make sure the child controllers have been initialized. It happens after parent initialization. So parent controller cannot make any initialization that depends on child. For example, cannot call this.editor.edit({}); while starting. Binding needs to be done after controller initialization into the link function. Having a link function means we cannot use component, must be directive. And the logic to locate child controllers isn't really nice, and would be worst if we have multiple child nodes. So turns out i found another solution to handle child components inputs and outputs in a normalized form, that does not rely on scope or any initialization order: RsJs Observables.
So now under userCrud controller i have a few observables that will be passed on child attribute bindings. UserCrud controller will listen into some of them, that will turn out to be child component outputs, and will send values into others, that will be child component inputs. This solution seems pretty good, since it is a normalized form of communication for both inputs and outputs, and since i can start userCrudController sending values into "users" observable, it does not really matter if userList has not been initialized. As soon as it gets initialized it will handle that value.
I believe this is a pretty decent solution after all. I know Angular 2 uses RxJS observables. Not sure if it uses the same way, but this makes sense to me and results into really independent components without any need for scope/watch and element handling. What do you think? |
My approach was a work-around, so there are of course many cases that are not handled. The downside of your approach is that the child controllers use stuff from a parent controller. I don't think observables offer much of a benefit in this case (although they are pretty cool in other cases 😃); you could just as well expose a function form the parent controller that the child controllers could use. The benefit of having children expose functionality and let the parent controller use it or ignore it, is that you your parent controllers aren't coupled to the children and don't need to have a specific "shape". E.g. one implementation of |
Indeed, the child to parent communication could be easily done by function binding from parent using '&', and the other way could be done by parent attribute watching (Maybe for this parent -> child observables might make more sense), but I prefered observables to be able to have a more common form of communication for both input and output. I believe that could be easier to teach the development team and maintain. Regards. |
Sure, any way that works for you and your team is fine. The "problem" still remains: The proposed @lucianogreiner , thx for the insights ! |
This works pretty well:
So i think it´s all a matter of pre-processing "as" attribute binding, isn't it?
|
The idea is that the (BTW, |
As far as the API goes, #14080 is more flexible (and has a higher chance of landing). Closing. |
Hello. I am thinking about having an application as a tree of components with 1.5.
Let's say we have:
If we want to reuse somewhere else, we should not depend on user-crud. Also, we want to reduce or eliminate the $scope and $watch usage as a good practice.
So, what i miss is a better clean way of communication from parent to its child components (crud to the list and editor) other than using events or directive require.
I believe this approach is not absurd, but it's not the way we used to code it using Angular. Maybe there could be something as a 'bindToParent' property to expose child controller into parent:
The problem i see with this approach is what could happen if we have a multiple user-list elements or a iteration of them inside an element.
What do you think?
The text was updated successfully, but these errors were encountered: