You can always walk through the hierarchy using a way shown above (starting from UI instance) or other way around: asking a parent and walking from bottom to top and then find a required ascendant. Then you may ask children of it.
But I would say this is not a proper way from design point of view.
It’s better to decouple the components and avoid the knowledge of each other.
I would better use some event bus: when you need to communicate between components one component should send an event and another component should listen for events and receive events.
I have made a simple UI-scoped @Component with wich I am able to get my MainView instance without walking through any elements hierarchy. I’m not sure if this classifies as event bus, but it gets the job done and could be expanded for events.
The trick is to inject this component both in the MainView, as well as in each child view. In the mainView you then only have to set the current MainView of the “Bus”.
@Component
@UIScope
public class MainViewBus {
private MainView mainView;
public MainViewBus() {
}
public MainView getMainView() {
return this.mainView;
}
public void setMainView(MainView mainView) {
this.mainView = mainView;
}
}
public class MainView implements RouterLayout {
public MainView(MainViewBus mainViewBus){
mainViewBus.setMainView(this);
}
public void someMethod(){
Notification.show("You just invoked a method on MainView from a child view.");
}
}
@Route("foo", layout = MainView.class)
public class FooView extends VerticalLayout {
public FooView(MainViewBus mainViewBus){
add(new Button("Test MainView Bus", click -> mainViewBus.getMainView().someMethod()));
}
}