-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Router: add support for routes like /orders/:id/edit
where the parameter is in the middle
#2740
Comments
Would this actually be the same as |
This functionality was left out from the design in order to keep it simple. The simplest workaround is probably to change the URL structure to The suggested workaround of using Some ideas for this could be supported:
|
On this regard, I find very intuitive and productive the JAX-RS approach, i.e. @Path("orders/{id}/edit")
public void editOrder(@PathParam("id") Long id) {
// ...
}
@Path("orders")
public class OrderRoute {
@Path("{id}")
public Component orderCard(@PathParam("id") Long id) {
// ...
}
@Path("{id}/edit")
public Component orderForm(@PathParam("id") Long id) {
// ...
}
} BTW I'm not sure this approach, which fits well for stateless APIs, would fit just as well in Flow. |
If we are going to support a placeholder syntax in The overall problem with any such approach is that it's based on boilerplate annotations with magic strings (e.g. It might still be that that boilerplate annotations or a magic convention is the price that must be paid for supporting this level of flexibility. It would still not be needed in simpler cases where the parameters are at the end of the URL. There is a separate discussion about allowing |
Moving here some thoughts from #3474: @heruan said:
@mvysny said:
@heruan said:
One of the apps I'm porting (from Aurelia) to Flow is growing fast and this would be really necessary for a smooth port. Could the scenario I described in my last comment above be approachable and fit all the use cases? |
@heruan I'm not sure I understand exactly how the different parts would work together in your example. I assume that e.g. the |
My example is a bit hermetic, I get it 😃 Instead of (or in addition to) a @Route("departments")
public class Department extends VerticalLayout implements HasUrlParameter<Long> {
// override setParameter
}
@Route("employees")
public class Employee extends VerticalLayout implements
HasUrlParameter<Long>, HasParentRoute<Long, Department> {
// override setParameter
@Override
public void setParentRouteParameter(Long departmentId) {
}
}
@Route("profile")
public class Profile extends VerticalLayout implements HasParentRoute<Long, Employee> {
// override setParameter
@Override
public void setParentRouteParameter(Long employeeId) {
}
} Or, for more complex case (e.g. one need a parameter deeper in the hierarchy) provide a map to obtain the parameter from the component class, e.g. |
The more use cases I'm facing while porting a structured app to Flow, the more it seems to me this could be combined to router layouts without refactoring the entire routing system, staying simple and straightforward for both developers and users. The culprit would be supporting For example, say I have a @RoutePrefix("users")
public class UserSectionLayout implements RouterLayout, HasUrlParameter<Long> {
^^^^^^^^^^^^^^^
HorizontalLaytour navbar = new HorizontalLayout();
VerticalLayout content = new VerticalLayout();
Long id;
public UserSectionLayout() {
this.add(navbar, content);
}
public Long getUserId() {
return this.id;
}
@Override
public void setParameter(BeforeEvent event, Long id) {
this.id = id;
this.navbar.add(new RouterLink(UserProfileRoute.class, id));
this.navbar.add(new RouterLink(UserOtherRoute.class, id));
}
@Override
public void showRouterLayoutContent(HasElement content) {
this.content.getElement().appendChild(content.getElement());
}
}
@Route(value = "profile", layout = UserSectionLayout.class)
public class UserProfileCard extends VerticalLayout implements HasParentLayout<UserSectionLayout> {
@Override
public void setParentLayout(UserSectionLayout parentLayout) {
Long id = parentLayout.getUserId();
User user = UserBackend.getUser(id);
}
}
@Route(value = "other", layout = UserSectionLayout.class)
public class UserOtherCard extends VerticalLayout implements HasParentLayout<UserSectionLayout> { /* ... */ } This would provide URLs like Plus, any component in the activation chain can get an instance of its parent layout and access any parameter in the hierarchy. Note: having parent layouts with URL parameters is the only way I can guess to add navigation links on them when their child components are parameterized too. |
It seems like both alternatives ( There could in theory be a monster like One potential solution to this could be some kind of fluid builder that would allow defining one set of parameters per method call instead of doing everything through only one One additional observation is that it's seems redundant to define We might still also want to support placeholders in the route mapping strings, e.g. for cases when a view needs to access parameters from multiple parent layouts. |
Totally agree, a builder would be versatile and safe.
Not necessary if layouts provide getters, since you can descend in the hierarchy, e.g. for @RoutePrefix("departments")
public class DeparmentsLayout implements HasUrlParameter<Long> {
// ...
public Long getDepartmentId() { /* ... */ }
}
@RoutePrefix("employees")
public class EmployeeLayout implements HasUrlParameter<Long>, HasParentLayout<DepartmentsLayout> {
// ...
public DepartmentsLayout getDepartmentsLayout() { ... }
}
@Route("profile")
public class EmployeeProfile implements HasParentLayout<EmployeeLayout> {
@Override
public void setParentLayout(EmployeeLayout parentLayout) {
Long employeeId = parentLayout.getEmployeeId();
DepartmentsLayout dl = parentLayout.getDepartmentsLayout();
Long departmentId = dl.getDepartmentId();
}
} I'd avoid placeholders in route mappings, which in my opinion would open a Pandora's box of convoluted logic to provide the values to the user in a typesafe way (if possible at all). |
Is it really that important to have URLs generated in a type-safe way? Are we willing to introduce all those builders and type safety and make users to use that, to avoid simpler but dynamic solution with placeholders? As if what happened to Scala was not scary enough. |
Everyone has their own preference when it comes to potential tradeoffs with type safety, so I think we should consider supporting both approaches. This would be in line with e.g. |
Note that URL format has been changed from `storefront/123?edit=` to `storefront/edit/123` which is more REST standard. Jira: BFF-614 Related with: Jira: BFF-354 vaadin/flow#2740
Note that URL format has been changed from `storefront/123?edit=` to `storefront/edit/123` which is more REST standard. Jira: BFF-614 Related with: Jira: BFF-354 vaadin/flow#2740
* Handle the edit verb in the URL for orders Note that URL format has been changed from `storefront/123?edit=` to `storefront/edit/123` which is more REST standard. Jira: BFF-614 Related with: Jira: BFF-354 vaadin/flow#2740 * Merge branch 'master' into fix/614-order-edit-url
A bit as an exercise (and much because we really need this to port our apps to Flow 😃) I've implemented a working-ish solution with router layouts: master...heruan:layout-url-parameters Basically, when a Then, any component in the chain implementing Of course this is not finished yet (all router tests succeed, but a couple of other tests regarding route aliases for viewport and theme still fail), but I'm sharing this so if the feature doesn't get into 10 it might help others who need it from the start! |
Any chance for this to be milestoned after 1.0 release? |
This is becoming more pressing as time passes; I'll try to give a different point of view than the URL-based already discussed here. Right now Flow assumes that parameterized views are leaves. This is quite restricting, since the subject identified by the parameter might need multiple independent views and provide links for them (for example, a customer view might have a view for details, orders, sold items, contacts, etc.). In cases like this, the parameterized view is also a router layout, providing navigation on its sub-views and possibly other common components. This could be worked around using multiple sibling parameterized view, with links on each of them to each other. But this workaround lacks a fundamental aspect: the "main" parameterized view cannot share its state with its siblings as it would be if it were a router layout with its children. I really hope this issue will be considered soon! |
There is now an implementation available as extension to Vaadin Flow by @fluorumlabs : https://vaadin.com/directory/component/url-parameter-mapping |
Thank you @samie for the link and @fluorumlabs for the great plugin! The POV I described before was about having parameterized router layouts, so to provide navigation links with the parameter to the sub-views. Do you think I need to open a new issue for that? I guess no, since it would also include this. |
@heruan this is on the maybe list at the moment and to be honest it looks unlikely it will make it. |
@pleku don't you think that readable hierarchical URLs are important? Is the task really so difficult to be implemented? If there are some not obvious difficulties, please share. It can help with creating PR... |
@remal I just checked the code, and I think the main problem is that this would require an almost full rewrite of |
@remal I've given a shot at this too (see master...heruan:layout-url-parameters) and used that for a while successfully but I couldn't keep maintaining my fork so now is not up-to-date. Still, it could be a starting point if the team could give some feedback! |
This is still blocking migration of some of our apps to Vaadin, any news about this? A version milestone maybe? 🙂 |
@heruan sorry not commiting to any milestones yet, but we have started to take a look "on the side" for making this happen in an upcoming minor release for Vaadin 14. I can promise that after the feature is done, it will be available in the next minor release train for Vaadin 14, which should be released within no more than three months after the feature has been done 😎 |
Great news @pleku, thanks! Do you have design specs for this? I'm especially interested in the role of router layouts, and how parameters will be available on their instances. |
We already have a quite smooth way for handling the common cases through the regular Based on those constraints, I would suggest placeholders in the When it comes to the placeholder syntax in the |
To be decided which Vaadin 14 minor this lands into. Probably 14.4 even though window is still open for 14.3. |
It would be great if it could land in 14.3 . |
Also to clarify here, this is now being shipped in 17.0.0 today, so please test it there. We would want to include this to 14-series as soon as possible, but we also don't want to ship anything in the LTS that is not "battle-proven". If it works out well, dropping out a comment here will work and asking "when is this coming to 14" to let us know we need to get this in. |
When defining a routes map of an application, as a developer, I want to use routes where the route parameter is not the last segment of the URL (e.g.
/orders/:id/edit
). With the new Router API that is not supported at the moment (flow-1.0.0.alpha6).The text was updated successfully, but these errors were encountered: