-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Could we get a component binding option of '>' for one way binding up to a parent? #15902
Comments
We recommend that you use |
What I implemented in the fiddle is somewhat the opposite of I realize there are currently ways to accomplish what is in my fiddle (since it's functional), but I believe there's room for clearer intent when creating a component binding structure that can communicate that a value is intended to be provided to the parent context from the child which currently doesn't exist. |
As another example, writing a filter/data display set of components could be as easy as something like this without the need for $scope.$watch in the child component or two-way binding.
|
yes |
So if I'm looking at this correctly, you want your child components to expose an API in such a way that a parent can call it and execute the component's internal code to, in this case, update its content, right? I don't really see the benefit over using When using a unidirectional data flow together with some kind of smart and dumb components I don't think this even has any use-case (or at least not one that necessarily needs this new binding). But feel free to correct me if I'm wrong here! From a reusability point of view, you'll want a component to represent the items (only have an |
@sonicblis I see what you mean now, but I tend to agree with @frederikprijck that this is not something we actually want people to do. In your filter example, I'm not sure why the filter component should be responsible for resetting te data, if you can just pass in an array from the parent. |
@frederikprijck, thanks for thinking this through. I should have left out the With your solution (moving data access higher), I can't ever have a child component that's also a smart component (that does display and has parent triggerable functionality) without continuing to I find myself solving this problem with a As one more simple example, if I have a graph component that displays a common roll up of data, and I want to use it multiple times, I could avoid every parent being responsible for data access, but instead encapsulate data access in the graph component itself with the ability to trigger a refresh from any parent if necessary. Thanks again for looking at this. Happy to contribute a PR if there's any hope. cc: @Narretz |
That's incorrect, I don't see why that would be impossible. You could perfectly move the data-access in the dumb component I mentioned, making it both responsible for data-access and visualisation (not a bad thing, just not that dumb/reusable). You can, if you want, later abstract the data visualisation part into a dumb component (but the data-access stays out of the dumb component). But that's about the new feature you're proposing, I personally don't see any use-case yet.
Here's a modified plunkr to demonstrate it: https://plnkr.co/edit/qb1NCLSeZgGPuRVDqnpg?p=preview |
@frederikprijck Your example works and all, but outside of Angular demos, I feel like allowing binding like that to flow through as DOM changes is an anti-pattern. https://plnkr.co/edit/PzNasQKuWVe0G4K4RfZw?p=preview Here I've taken your example, added an extra field, and put a search button on it. I've got So you're forced to re-create the |
@langdonx, not to mention the search that will take place with default params since the @frederikprijck, Here's another example of where it would be nice to have a https://jsfiddle.net/sonicblis/p630v7uf/3/ And then here, where the child is running some complex logic before returning a complete and valid edited entity. https://jsfiddle.net/sonicblis/p630v7uf/4/ All doable with the current bindings, but would be better with one-way binding from child to parent. It seems like such a win to be able to define "out params" in the child's interface that you can then access from the parent. |
It might not feel very intuitive in the beginning, but it's not bad from a performance point of view to use immutables as it eliminates the need for deep watches. @sonicblis I'm not a fan of two-way binding, but I wouldn't really structure components as how that fiddle does. If you have the need to implement your components that way (have the save button outside your component and retrieve the child component's state when necessary) I think it's what two way binding was introduced for. It makes the fiddle do the same with less code: https://jsfiddle.net/s8csjnyn/1/ . The second fiddle is a bit harder to implement that way. Components are generally push based, not pull based. So pulling state out of the component feels unintuitive. Moving the complex business logic outside the inner component but inside the save handler should also remove the need for the |
There's a PR for something that achieves this differently: #14080 With this, you can publish a component into its parent scope. This is very useful for sibling communication, but could also be used for parent - child communication. It would not be enforced by a strict interface, though. |
The ability to avoid two way binding seems like it would be enough of a gain. Seems like there's no trade off for the benefit. Also, I'd hate to put my complex business logic in every parent that's going to use that editor when I could nicely encapsulate it in the editor. I don't get the downside. Can you help me see how this is actually a negative instead of how I can make due without it? I'm not suggesting that there's a need for |
@sonicblis Only taking Angular into account, I wouldn't say merging this is a good idea (not saying it won't get merged tho) unless Angular has comparable solutions. We'd be introducing an un-upgradable feature if Angular is not planning to implement this as well. It doesn't sound a lot like how (web) components are to be used either.
Nobody is asking you to do that. If you currently have your editor as a single component ( I guess it depends on what kind of BL. Looking at your BL it looks like it's some logic that's being applied to the object before using it outside the directive, this sounds a lot like what a Imho there's 3 solutions to solve this with current AngularJS setup:
|
None taken, don't worry about it. 😉 @Narretz Yep,
|
You either missed a part of your reply, or I'm missing what you're talking about. 😕 |
@frederikprijck Sorry, just messing around. Was trying to express my disapproval of your implication that I'm new to this. |
@langdonx I had no intention to call you new at all (other than the unintuitivity of immutables). You said it feels unintuitive to re-create the object. I wanted to state it feels unintuitive at first (so when recreating the objects for the first time for these purposes) but has some benefits in the long run and might feel a lot less unintuitive at the end. |
I'm familiar with $validators and $parsers, but I appreciate the suggestion.
It seems like the closer we can get to components having a well defined interface, the better, so I'm not sure I agree with this being against the goals of components in general. The lack of upgrade path to Angular 2 is a great point. Looks like it's just a whole hog exposure of controllers in that world which is a little surprising, but gets the job done. I echo Lang's ask about the PR for ngAs. Any chance that's getting merged some time soon? |
This thread has grown long and I am not sure what all the arguments usecases are, but I will try to answer/give my view on some of them:
As already mentioned, the recommended way to pass value one-way to the parent is the
The way I understand it, this is irrelevant to the problem you are trying to solve, which is "who sets the value on the parent" (not the child). So, even in the
There is still a performance hit (for one-way watching). If performance is a concern, the I think the main issue with what you suggest, is that enabling child-components to modify the parent at will (even a specific property only), removes much of the declarativeness that we know and love in AngularJS. This is quite different than letting the parent modify the child, because a child can have only one parent, the opposite is not true (one parent --> multiple children). A solution to that, is to still let the parent be in charge. This is achieved by Angular's outputs (where the parent has to explicitly subscribe to emitted output values and handle them as it wishes) and AngularJS' All than being said, I don't think there is something that is not possible with the current API. It's just more verbose than necessary/desired. I understand that currently the child-to-parent communication story in AngularJS isn't great and requirs a bit more boilerplate than we'd want it to. But as already mentioned, I don't think it is wise to introduce new features that do not map closely to Angular semantics as this will make upgrading more difficult. Even more so, when there are alternatives that are more declarative and more in-line with "how Angular does it". WRT to previously mentioned alternatives: a) An Angular-like, Eventemitter-based "output" binding. Besides, being more similar to Angular, (a) won't be much different than (b) is similar Angular's template-local refs and would also make it easier to access child methods from the parent (in some usecases at least). The problem with The bottom line is that I don't think the proposed feature is a step in the right direction, but we should work on alternative approaches that are more "upgradable" and declarative. |
That nails it. I appreciate the discussions and look forward to that friction being slightly reduced if that's what the future holds. =] |
I'm submitting a ...
Current behavior:
Right now, the only option for passing values out of a child component to a parent is the
'='
two way binding which everyone agrees should be avoided. Parent values will overwrite child values in this case.Expected / new behavior:
With a
'>'
binding, an author could explicitly communicate that the child is going to be providing this value and whenever it changes, it should be set to this parent property. You also avoid the performance hit of the two way binding.Minimal reproduction of the problem with instructions:
This fiddle gives an idea of what I'm suggesting.
Angular version: 1.6.3
Browser: all
The text was updated successfully, but these errors were encountered: