Sharing data & state between components #5449
-
Looking to spark a discussion into methods to enable components to communicate with each other without becoming dependencies of each other. BackgroundA situation I run into sometimes is I need to create a generic-like wrapper component that can add extra functionality to, or manage state between other components. A simple example would be Telerik's Cascading ComboBox, and a more complex case is WinUI's SemanticZoom. Both examples have different use cases and requirements, but the common theme here is they both have a wrapper element around some general use controls that is able to share data and state with all of its children. Goals
Current Ideas
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 8 replies
-
Clarifying question: Does the wrapper need to get data from the children or do the children need data from the wrapper or does it need to go both ways? |
Beta Was this translation helpful? Give feedback.
-
Ok, you've got a few options. If you want the parent component to work with any direct child, then I recommend that you use the slotted directive to keep a sync'd array of child nodes and get change notifications when children change. When a change happens, you can loop through the slotted children and manipulate them in whatever way you want. So, if you want to check them to see if they support a specific API, such as having a If you have more complex structures involved, you may want to have children fire events. Using the A third option is to use a shared state or service object, provided by DI. The shared object can be injected into the parent and injected into the children. This object can then be used as a communication channel between the two. By default, the DI system makes these singletons. So, if you have multiple instances of the parent element in your app, and you don't want all parents sharing the same object, you need to explicitly handle that. One way you can do that is by creating a new DI container, scoped to the parent element. Then explicitly register the shared service in that container and only descendants of that parent element will be able to inject that specific instance. Note that this works regardless of the DOM structure. The reason for this is that container location for an element works using the event pattern described above. It's just a very general purpose solution built on top of that, which adds object lifetimes and other features. The mechanism also has some perf optimizations that enable it to avoid events for container location in certain scenarios if needed. A fourth option is that you could create an event aggregator that enables non-DOM based pub/sub, and use that to communicate between elements. Because this isn't DOM-based, it's not best suited if you need parent/child communication. However, you can put the event aggregator in DI and use the same technique as above. I personally only use event aggregator when I need one global aggregator to facilitate communication between components independent of DOM structure. This tends to focus around loosely coupled business events. So, imagine you have a Auth service and it raises an event when the user is logged in/out. You could have components across your entire app subscribe to that domain event and respond in their own way. Hope this helps! |
Beta Was this translation helpful? Give feedback.
Ok, you've got a few options.
If you want the parent component to work with any direct child, then I recommend that you use the slotted directive to keep a sync'd array of child nodes and get change notifications when children change. When a change happens, you can loop through the slotted children and manipulate them in whatever way you want. So, if you want to check them to see if they support a specific API, such as having a
value
property, you could do that. The nice thing about this is that the logic is in a single element (the parent) regardless of what type of child you add. As long as the child elements conform to some interface, the parent can work with them. If you need child no…