1

As to the suggestion that this question has already been answered, that answer suggests a workaround solution that does not solve my use case.

  • The answer referenced suggests using 2 routes, hence the title of my question which stipulates without having to to define a second route Using 2 routes creates a problematic browser history.

  • If avoidable, I do not want to use a query string parameter or hash.

  • I do not want to use a child route because that would require the use of a secondary router outlet, which will add a level of complexity to my application that I have to believe is avoidable.

My route has 2 parameters, one being optional. It is a lazy loaded route, but I assume this should not matter as it relates to my question. If it does matter please let me know.

The route:

{ path: 'list/:name/:type', loadChildren: './list/list.module#ListModule'},

The :name parameter is required for this route to load correctly, but the :type parameter is optional.

I tried defining 2 separate routes and setting both to point to the same component, one with the parameter and one without, but this is not a working solution in my case.

I'd like the browser's history to be correct and reflect the addition of, or update to the optional :type parameter via user interaction without requiring navigation to another route causing the component to reload.

So, it is the initial route entry that is the problem. Once the :type parameter has been defined the first time, subsequent changes would not require a route change.

I'd like to ask, specifically, is it possible to define an optional parameter for a route in Angular?

Or, as a solution to this problem, is it possible to update the route / URL after the route has instantiated without triggering navigation?

DevMike
  • 1,630
  • 2
  • 19
  • 33
  • check this one https://stackoverflow.com/questions/39752442/different-routes-same-component – Veselin Davidov May 02 '18 at 07:03
  • 1
    thanks, I have seen the child route example, but this requires using a secondary router-outlet which would add a huge level of complexity to my component and page that i have to believe is avoidable? i'll update the question to reflect this. – DevMike May 02 '18 at 07:08
  • If the second parameter is optional why make it part of the path? Query parameters seem like a much more natural fit and it's unclear why that's considered not "pretty". – jonrsharpe May 02 '18 at 07:12
  • Possible duplicate of [Angular 2 optional route parameter](https://stackoverflow.com/questions/34208745/angular-2-optional-route-parameter) – jonrsharpe May 02 '18 at 07:13
  • I hear ya, i'd personally be fine using a query parameter. For whatever reason my client is pushing back hard ... But if query strings are only way to achieve one, ill have to tell them they are out of luck! – DevMike May 02 '18 at 07:15
  • Have you tried to set up a route that redirects `'list/:name'` to `'list/:name/'`? – Daniel W Strimpel May 02 '18 at 07:18
  • If you mean to suggest redirect to same path with an added trailing slash, this creates another problem. It breaks the back button. The user will not be able to navigate back to the route prior to entering this one. – DevMike May 02 '18 at 07:32
  • OK — there IS a way in Angular to define an OPTIONAL parameter. The irony is, it still results in an 'ugly' url? but the point here is that there IS a way to define an optional parameter. https://vimeo.com/192319999 – DevMike May 02 '18 at 08:20
  • 1
    You seem surprised; it's in the docs https://angular.io/guide/router#route-parameters-required-or-optional – jonrsharpe May 02 '18 at 08:36
  • hah! somehow i missed it, but i am going to share this in greater detail in an answer since using a matrix url comes with implications. – DevMike May 02 '18 at 09:19
  • I do think this is a duplicate of https://stackoverflow.com/q/34208745/1751497 and I think that the most correct answer is actually this one: https://stackoverflow.com/a/56391974/1751497 – rooby Oct 12 '21 at 01:25

1 Answers1

3

As it turns out Angular does actually offer a way to use optional parameters.

Although this still does not solve the fact that the initial instantiation without the parameter present will still require navigation to arrive at the same route with the parameter present. I was trying to avoid triggering a reload in the browser.

Thank you @johnsharpe for pointing this out i do not know how i missed it. It's intended use solves situations that require more complex url structures, but this is the correct answer.

Angular docs on optional params

After a lot of digging around, i also came across this video Angular Tutorial on Parameterized Routes which actually covers my use case, how to define an optional parameter in Angular, and why you might need to use one in-order to maintain functional browser navigation. The answer that Veselin Davidov referenced above creates a problematic browser history. How? The reason is explained approximately 11 minutes into the video.

To implement a route parameter as optional, you first define a route without the optional parameter present. Using my case as an example, i define my route with the required :name parameter only:

{ path: 'list/:name', loadChildren: './list/list.module#ListModule'},

And then when navigating to this route from within my application, i can define the optional :type parameter like so using an object with key/value pairs:

this.router.navigate['list', name, {type:value}];

instead of this:

this.router.navigate['list', name, type];

This approach uses matrix url notation. The resulting url has a semicolon and looks like this:

mysite.com/list;type=value

When sharing and/or reloading this resulting url, Angular will pick up the matrix parameter and make it accessible as a route parameter.

Ironically though, using a matrix parameter has other implications and as such this might not be an advisable approach. See this question/answer for more detail.

So, you might be thinking, as i did, then whats the difference? why not just use a query string parameter instead? see this on differences between matrix and query

DevMike
  • 1,630
  • 2
  • 19
  • 33
  • See this page for what I think is the best answer: https://angular.io/guide/routing-with-urlmatcher - That way you don't have to use any unusual URL formats and you can reuse the same component across many different paths. Also see this answer: https://stackoverflow.com/a/56391974/1751497 – rooby Oct 12 '21 at 01:25