Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 routing: Is it possible to add constraints to route parameters?

I want to match for a language in my routing service. My problem is that the language needs to be first in my route.

For example:

/en/xxx

/fr/xxx

/en/yyy

/fr/yyy

Since I want to use this parameter i have added the following route

{ path: ':lang',  children: [
      {path: '', redirectTo: 'xxx', pathMatch: 'full'},
      {path: 'xxx', component: x},
      {path: 'yyy', component: y}
]}

The issue is that everything matches :lang.

For example:

/abc/xxx

I would like to add constraints to this so that I can say that :lang can only be of type <'nl' | 'fr' | 'en' | 'de'>.

Now when I want to go to /robots.txt (which should show me the robots.txt file) it maps to :lang and sends me to "/robots.txt/xxx"

I have tried mapping every language separately but then i don't have access to the route parameter.

I have tried adding the robots.txt above but since it's a assets file, i don't know how to show it by adding a line in the routes.ts file.

I have tried adding an exception in the route guard but then I can't redirect to robots.txt since it just keeps mapping on the :lang parameter.

This is my current routes.ts file:

{path: '', redirectTo: '/xxx', pathMatch: 'full', canActivate: [LangGuard]},
{path: 'xxx', component: xxx, canActivate: [LangGuard]},
{path: 'yyy', component: yyy, canActivate: [LangGuard]},
{ path: ':lang', canActivate: [LangGuard], children: [
      {path: '', redirectTo: 'xxx', pathMatch: 'full'},
      {path: 'xxx', component: x},
      {path: 'yyy', component: y}
]}

My LangGuard is pretty extensive but ill write a short version down:

Get route parameters
If parameter is "nl", "fr", "de" or "en"
then return true //do nothing
else router.navigate('/' + decideLanguage() + state.url) // redirect to new url

Maybe a little overview of what i want to achieve and what i am getting:

What i want

/ -> /en/xxx
/abc -> /en/xxx
/xxx -> /en/xxx
/yyy -> /en/yyy

/en/xxx -> ok
/fr/xxx -> ok
/de/xxx -> ok

/en/abc -> notfound

/abc/xxx -> notfound
/abc/yyy -> notfound


/robots.txt -> ok

What I have

/ -> /en/xxx
/abc -> /en/xxx
/xxx -> /en/xxx
/yyy -> /en/yyy

/en/xxx -> ok
/fr/xxx -> ok
/de/xxx -> ok

/en/abc -> notfound

/abc/xxx -> ok (WRONG)
/abc/yyy -> ok (WRONG)


/robots.txt -> /robots.txt/xxx (WRONG)

NOTE: I can't use redirectTo for the language because the language is selected according to the localstorage, thats why i am using the routeguard

If I need to add more information or you have some questions, feel free to ask and I will answer them to the best of my abilities.

Thank you

like image 308
Ken Bostoen Avatar asked Feb 04 '19 08:02

Ken Bostoen


People also ask

How does Angular routing handle route parameters?

To access the route parameters, we use route. snapshot , which is the ActivatedRouteSnapshot that contains information about the active route at that particular moment in time. The URL that matches the route provides the productId . Angular uses the productId to display the details for each unique product.

What would be the correct way to declare a route with an optional parameter name?

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.

Where do you set the route parameter value in Angular?

First, add links to the two components. Assign the anchor tag that you want to add the route to the routerLink attribute. Set the value of the attribute to the component to show when a user clicks on each link. Next, update your component template to include <router-outlet> .

How are parameters identified in the route configuration in Angular?

The first way is through the route snapshot. The route snapshot provides the initial value of the route parameter map (called the paramMap ). You can access the parameters directly without subscribing or adding observable operators. The paramMap provides methods to handle parameter access like get , getAll , and has .

What is route parameter in angular?

Route parameters allow us to send dynamic data through a route by appending it to the URL as a segment. For example, if we want to send a user’s ID to another component, we could do it with a route parameter. The URL would look something like the following.

What is activatedroute in Angular 2?

The ActivatedRoute is a service, which keeps track of the currently activated route associated with the loaded Component. The Angular adds the map all the route parameters in the ParamMap object, which can be accessed from the ActivatedRoute service The ParamMap makes it easier to work with parameters.

Is there a CLI command to set up routing in angular?

There's no separate CLI command to set up the routing for you. In this lesson, I'll show you how to manually add routing to your Angular application. If you wanted to keep your routes in a separate module, you could do that by creating an app-routing module by using this Angular CLI command:

How to pass static data to route in angular?

The Angular can pass data to Route in several ways. We can configure the static data at the time of defining the route. This is done by using the Angular route data property of the route.


1 Answers

I would give a try to Angular UrlMatcher . With that you can define your own url matching function. IMHO The guards are more meant to check authentication, not to check if the route is valid or not.

Here goes an example:

Routing

export function checkLang(url: UrlSegment[]) {
  return url[0].path.startsWith('en') || url[0].path.startsWith('fr') || url[0].path.startsWith('de') || url[0].path.startsWith('nl') ? ({consumed: url}) : null;
}

export const routes = [  matcher: checkLang, component: TestComponent, children: [
      {path: '', redirectTo: 'xxx', pathMatch: 'full'},
      {path: 'xxx', component: x},
      {path: 'yyy', component: y}
]}]

and then the TestComponent

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-test',
  template: '<div>HELLO</div>'
})
export class TestComponent implements OnInit {

  constructor(
    public route: ActivatedRoute,
    public router: Router
  ) { }


  ngOnInit() {
    console.log('LANGUAGE: ' + this.route.snapshot.url[0].path); // here you get the language and you can act consequently 
  }
}
like image 196
JavierFromMadrid Avatar answered Oct 10 '22 20:10

JavierFromMadrid