Add a method to find the active view (or parent view/layout)
See original GitHub issueDescribe your motivation
When building re-usable components they often need to interact with other parts of the UI, like the current view, navigation menu or some shared parts in some parent layout. Those are most often components in the current component tree, but in Vaadin provides no easy way to search them up. Instead we then inject them to other components using Spring/CDI or build application specific hacks to get references to them.
Providing a way for developers to seek views from the active UI might make it easier to create re-usable code.
Describe the solution you’d like
A code example of a method (that could be placed to the UI class with minor changes):
/**
* Finds a reference to the current view or parent layout of given type.
*
* @param viewType the class of the view or parent layout to search for
* @return the view or empty optional if given view is not active
* @param <T> the type of the view or parent layout to look for
*/
public <T extends Component> Optional<T> findView(Class<T> viewType) {
List<HasElement> activeRouterTargetsChain = UI.getCurrent().getInternals().getActiveRouterTargetsChain();
for (HasElement element : activeRouterTargetsChain) {
if (viewType.isAssignableFrom(element.getClass())) {
return Optional.of((T) element);
}
}
return Optional.empty();
}
The implementation would be pretty much the same as in a private helper introduced in https://github.com/vaadin/flow/pull/13906
Then e.g. a single component could call a method in main layout like this:
ui.findView(MainLayout.class).ifPresent( main -> main.makeNewMessagesIndicatorBlink());
Describe alternatives you’ve considered
Write all code into single class and all problems are solved 🤓
Alternatively, Component could have a following helper:
/**
* Finds a parent component of given type.
*
* @param componentType the class of the component to search for
* @return the component
* @param <T> the type of the component
*/
public <T extends Component> T findParent(Class<T> componentType) {
Optional<Component> parent = getParent(); // see, parent here is Optional as well :-)
while (parent.isPresent()) {
Component component = parent.get();
if (componentType.isAssignableFrom(component.getClass())) {
return (T) component; // or Optional.of((T) element);
} else {
parent = component.getParent();
}
}
return null; // or Optional.empty() or throw
}
Additional context
I have been missing this kind of functionality in my own apps couple of time, but got the idea to bake this into actual proposal while working on improving the routing & navigation docs related to https://github.com/vaadin/flow/pull/13906 & https://github.com/vaadin/docs/issues/1482
Issue Analytics
- State:
- Created a year ago
- Reactions:4
- Comments:8 (7 by maintainers)
Top GitHub Comments
I talk about views all the time. For me “route maps the view to a certain URL” or “route is a view that is mapped to a certain url”. I had a findRoute originally as the method name, but then again, that is also returning “parent layouts”. Some of them define parts of the url/route, but not all. But I’d bet with both versions people could find it.
And yeah, the verb should be
get
if not returning Optional. My spine reads null checks better than Optional clauses, so I’m not a big fan of Optional either. On the other hand, we have already spoiled the framework with Optional usage, so I don’t have strong opinions on its usages. The @vaadin/flow team decides and my guess is what I had in the draft.I wonder how common it is to search for views/routes from siblings/children 🤔 If not there could be an alternative solution for the very same problem, that might be even more helpful (would not just find views (or routes and their parent layouts)). The following method could be added to the Component class, so we could also get rid of one dance to get the UI reference (with UI.getCurrent() or Optionals that we all love 😂) :
This ticket/PR has been released with Vaadin 23.2.0.