Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
TomVanDoo
Active Contributor

intro


When building large and complex UI5 apps, you will probably at some point start creating reusable components which you embed in a container app. The advantage of such a reusable component is that you can repeatedly use it in several apps. For most of the scenarios, the standard UI5 doco will suffice, until you need to have routing in a subcomponent, and deeplinks that you can share with colleagues.

So imagine you have a parent component with 2 routes, that each show their respective subcomponent:

  • project

  • reservation


And your reservation component has 2 routes:

  • list

  • detail


Scenario sounds simple enough, right?

The official way


The official UI5 doco requires you to specify the parent route in your subcomponent. That is for me a big nono, since the child component must be parent agnostic. Otherwise, it's not really a reusable component, since it will only work in those parent components that are predefined.

Secondly, I tried that approach, and for some reason, if you simply copy paste the url to another session, the parent routing isn't applied, since the router of the parent can't match the full route ("reservation/detail/50") to any of its own patterns.

In other words: the standard way just doesn't cut it.

Wildcards


So I decided to take a different approach and play with wildcards.

I defined my parent routes as following:
{
"pattern":"project",
"name":"project",
"target":["project"]
},
{
"pattern":"reservation/&:child*:",
"name":"reservation",
"target":["reservation"]
}

*Notice the use of the ":child*:" parameter. It's an optional wildcard that catches anything trailing the URL. This will ensure that "reservation/detail/50" is also considered as a valid reservation route by the parent router.

**you'll also notice how I added ampersands to separate the parent part and the child part. This helps the router to distinguish the patterns if your child and parent component happen to have the same parameter names, or URL parts.

the childroutes are defined as following:
{
"pattern": ":parent*:&/list",
"name": "List",
"target": ["List"]
},{
"pattern": ":parent*:&/Detail/{ResId}",
"name": "Detail",
"target": ["Detail"]
},{
"pattern": ":parent*:",
"name": "home",
"target": ["List"]
}

*Notice how this time, there is a leading wildcard for parent information. The last route contains only the parent wildcard, and is meant to show the default target (List). That way the URIs "reservation/" and "reservation/list" will both show the reservation list.

So this works perfect to recognize the URLs and show the right targets.

There is however still a catch. When you navigate internally in the reservation subcomponent, you may have a navto("detail",{ResId:50}) statement. This would replace the complete URL hash to "/detail/50", which is not recognized by the parent component. So if you share that URL, it wouldn't work, since the result in the app would be the project-list. In other words, we need to have a solution to automatically inject the parent, and child route-parts in the navigation parameters.

Fortunately, I inherit all my controllers from my own BaseController, in which I have some convenience methods. (like: getRouter, getModel etc...). So I just added a couple more convenience methods:



First of all, I defined an onRouteMatched handler that simply takes the navigation-parameters and keeps them in a simple variable. You can consider other options:

  • keep it in a settings-model

  • move everything to the component, and define a nice property on the component

  • ...


To automatically consider the parent and child properties during navigation, I added another convenience method (navTo). That way, in your controller, you can just call
this.navTo("Detail", {ResId:50});



inside the navTo method, I combine the navRoute property (containing all parent and child parameters and anything else) and your specific parameters into a new resultParams object and pass that to the router.

*yes you could use jQuery.extend here, but I refuse to depend on jQuery.

**no you can't use Object.assign, since it doesn't cater for deep structure. Although theoretically, you wouldn't have deep parameters in routing. But I already hacked that as well.

advantages



  • You don't need to define the parent route in your child component, so you have true reuse. No matter where you use this child component, the routing will work

  • having a simple navTo method means you don't have to worry about anything beneath the bonnet.

  • You can use parent and child routing in the same pattern, meaning you can have multi-level routing (Inception!)


disadvantages



  • you need to add parent, child wildcards in your route patterns...

4 Comments
Labels in this area