desired route display in browser URL

Viewed 215

I have routings like this in my main module routing.

    const routes: Routes = [
    {
        path: '',
        redirectTo: 'home',
        pathMatch: 'full',
    },
    {
        path: 'home',
        component: MainComponent,
        children: [
            {
                path: '',
                loadChildren: () => import('../HR/human-resources.module').then(m => m.HumanResourcesModule),
            }
        ]
    }];

and in the human-resources-routing.module.ts I have routings like this.

    const routes: Routes = [
    {
        path: '',
        children: [
            {
                path: '',
                component: QuestionGroupComponent
            },
            {
                path: 'reports',
                component: DatePeriodComponent
            },
            {
                path: 'states',
                component: StateWithTopPersonnelComponent
            },
            {
                path: 'personnel',
                component: StatePersonnelComponent
            },
            {
                path: 'personnel-detail',
                component: PersonnelDetailComponent
            }
        ]
    }];

For example now when I want to go to DatePeriodComponent I have a URL like this http://localhost:4200/home/reports but something which I want to show is a bit different. I want to show the URL like this http://localhost:4200/reports without home for all of my routs. How can I omit that or prevent to show in the URL?

2 Answers

I think a way to solve this is to use a custom UrlSerializer.

DefaultUrlSerializer is the default implementation of UrlSerializer and it's used, for instance, by Router.parseUrl() method:

urlTree = this.urlSerializer.parse(url);

or when setting the browser's URL(which might be what you need for your problem):

private setBrowserUrl(
      url: UrlTree, replaceUrl: boolean, id: number, state?: {[key: string]: any}) {
    const path = this.urlSerializer.serialize(url);
    state = state || {};
    if (this.location.isCurrentPathEqualTo(path) || replaceUrl) {
      // TODO(jasonaden): Remove first `navigationId` and rely on `ng` namespace.
      this.location.replaceState(path, '', {...state, navigationId: id});
    } else {
      this.location.go(path, '', {...state, navigationId: id});
    }
  }

A URL is a serialized version of a UrlTree. As a result, a UrlTree is the deserialized version of a URL. The DefaultUrlSerializer uses a UrlParser to deserialize a URL string:

  parse(url: string): UrlTree {
    const p = new UrlParser(url);
    return new UrlTree(p.parseRootSegment(), p.parseQueryParams(), p.parseFragment());
  }

So what you could do to solve this problem is to provide a custom implementation of UrlSerializer:

// In `providers` array
{ provide: UrlSerializer, useClass: CustomImplOfUrlSerializer },

A possible(and basic) implementation could be to use alter the returned value of DefaultUrlSerializer.serialize(urlTree) in CustomImplOfUrlSerializer.serialize(urlTree), by replacing /home with '':

class CustomImplOfUrlSerializer implements UrlSerializer {
  serialize (urlTree: UrlTree): string {
    const raw = (new DefaultUrlSerializer()).serialize(urlTree);

    return raw.replace('/home', '')
  }
}

Also, if you'd like to read more about UrlTree and why it is useful, I'd recommend checking out this article.

That was the simplest way I've ever seen and I'm the angriest person in the whole world now... I did it just like this by setting an empty string to load the default module and component. I considered the dashboard module as my default module and dashboard component as my default component. Now when the app comes up I can see this URL http://localhost:4200

const routes: Routes = [
    {
        path: '',
        component: MainComponent,
        canActivate: [AuthGuard],
        children: [
            {
                path: '',
                loadChildren: () => import('../dashboard/dashboard.module').then(m => m.DashboardModule),
            },
            {
                path: 'HR',
                loadChildren: () => import('../HR/human-resources.module').then(m => m.HumanResourcesModule),
            },
        ]
    },
   
];

and in my dashboard module

const routes: Routes =
    [
        {
            path: '',
            canActivate: [AuthGuard],
            component: DashboardComponent
        },
    ];

Related