Open mvysny opened 4 years ago
The current workaround: The code for walking through the registered routes and rewriting the parent layout:
private void reconfigureRoutesForAppLayout(Router router) {
//We have some exceptions that should not show the menu...
Set<String> rootLayoutOnlyViews = new HashSet<>();
rootLayoutOnlyViews.add("com.example.LoginRoute")
RouteRegistry routeRegistry = router.getRegistry()
List<RouteData> routes = routeRegistry.getRegisteredRoutes().stream().filter({ routeData -> !routeData.getParentLayouts().contains(AppLayout.class) }).filter({ routeData -> !rootLayoutOnlyViews.contains(routeData.getNavigationTarget().getName()) }).collect(Collectors.toList())
List<Class<? extends RouterLayout>> parentChain = new ArrayList<>()
parentChain.add(AppLayout.class)
parentChain.add(RootLayout.class)
if (routes.size() > 0) {
log.info("Reconfiguring " + routes.size() + " routes to use AppLayout")
routes.forEach({ routeData -> replaceRouteWithNewParentChain(routeRegistry, routeData, parentChain) })
}
}
private void replaceRouteWithNewParentChain(RouteRegistry routeRegistry, RouteData routeData, List<Class<? extends RouterLayout>> parentChain) {
log.info("Reconfiguring: " + routeData.getNavigationTarget().getName())
routeRegistry.removeRoute(routeData.getNavigationTarget())
routeRegistry.setRoute(routeData.getUrl(), routeData.getNavigationTarget(), parentChain);
}
Yet another workaround approach could be to have generic components in the shared jar file and with minimal subclasses that only introduce the @Route
annotation in each war file, e.g.
@Route(value = 'users/add', layout = AppLayout.class)
public class AppUserAddView extends SharedUserAddView {
}
Vaadin 14.1.x.
In bigger apps it could happen that certain
@Route
s are reused between different apps, for example user management-related routes would be published in customer's Nexus as a jar artifact, then linked to multiple WAR projects.The problem is that every WAR app defines its own parent layout specific to that app; the user management-related routes therefore can't use the
@Route(value = 'users/add', layout = AppLayout)
annotation because they do not have theAppLayout
class on the classpath.Currently the solution is to either use
@Route(registerAtStartup = false
, then discover the routes manually (or automatically by using customized classpath scanning solution), then register the routes intoRouteRegistry
; alternatively you can visit the registered routes in the registry and modify their parent layouts. The API is not simple and so this approach can be error-prone.I'd suggest to be able to set a closure somewhere to Vaadin, and that closure would be called for every route discovered. The closure should then be able to tell a different layout class to use; Vaadin should then automatically compute the parent chain from that layout class.