23

I have an Angular 5 application.

I have the following code in my app component.

I want to hide navbar and topbar for particular routes.

Is it possible to get currently activated route in app.component.ts ? if so, How ?

If not possible, is there any solution to resolve this ( using guards or whatever else ... )?

enter image description here

Also keep in mind that it should be reactive. when i switch to another route sidebar and navbar should show again.

Badis Merabet
  • 13,970
  • 9
  • 40
  • 55

4 Answers4

17

Try this:

in app.component.ts

import { Component } from '@angular/core';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { filter, map, mergeMap } from 'rxjs/operators';
import { Observable } from 'rxjs/Observable';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
  showSidebar$: Observable<boolean>;
  private defaultShowSidebar = true;

  constructor(
    private router: Router,
    private activatedRoute: ActivatedRoute,
  ) {
    this.showSidebar$ = this.router.events.pipe(
      filter(e => e instanceof NavigationEnd),
      map(() => activatedRoute),
      map(route => {
        while (route.firstChild) {
          route = route.firstChild;
        }
        return route;
      }),
      mergeMap(route => route.data),
      map(data => data.hasOwnProperty('showSidebar') ? data.showSidebar : this.defaultShowSidebar),
    )
  }

app.component.html

<aside *ngIf="showSidebar$ | async">Sidebar here</aside>

<router-outlet></router-outlet>

<a routerLink="/without-sidebar">Without sidebar</a>
<a routerLink="/with-sidebar">With sidebar</a>
<a routerLink="/without-data">Without data.showSidebar</a>

app routes

RouterModule.forRoot([
  { path: 'with-sidebar', component: WithSidebarComponent, data: { showSidebar: true } },
  { path: 'without-sidebar', component: WithoutSidebarComponent, data: { showSidebar: false } },
  { path: 'without-data', component: WithoutDataComponent },
])

You can modify it as you please.

Live demo

Tomasz Kula
  • 16,199
  • 2
  • 68
  • 79
  • I saw demo. Looks very interesting . I am integrating it now ! – Badis Merabet Apr 03 '18 at 14:37
  • @BadisMerabet nice :) Please upvote or accept my answer if you found it useful. – Tomasz Kula Apr 03 '18 at 14:41
  • Surely i will upvote and accept it as answer. do the same with my question :) . I think i just need to put `showSidbar: true` by default without having to mention it every time in routes. do you have an idea how to fix this ? – Badis Merabet Apr 03 '18 at 14:53
  • 1
    Check out my edit, you just need to change the last `map` function to check for the 'showSidebar` property in the route's data object. – Tomasz Kula Apr 03 '18 at 15:05
  • 1
    Best Answer . Concise and complete ! Thanks. – Badis Merabet Apr 03 '18 at 15:12
  • I very much like this approach. however, If you add `tap(data => console.log('data: ', data)` after the last `map()`, you'll notice, that after each navigation the observable will emit one time more. E.g. 1st router-click one log-message, 2nd will add 2 log-messages and so on. I temporarily fixed this by adding `distinctUntilChanges()` after the map. So It will only emit once with the same content. _But if you find a way to fix this issue please let me know._ – LuckyLikey Jul 25 '19 at 12:07
4

To get the active route without subscribing to router events, you can simply use a while loop recursively to find the lowest child.

private getActivatedRoute(): ActivatedRoute {
    let route = this.router.routerState.root;
    while (route.firstChild) {
        route = route.firstChild;
    }
    return route;
}
asdf
  • 952
  • 14
  • 13
3

Sure. you can filter router events and get only activated routes, and then, you can find some info about each route inside (sorry, can't really say right now, but as I remember, you should get only "activated right now" routes, which looks like what you're searching for):

constructor(private _router: Router) {
  _router.events
    .filter(event => event instanceof NavigationEnd) 
    .forEach(item => {
      console.log(item);
      console.log(_router.routerState.root);
      console.log(_router.routerState.root.firstChild);
    });
}
P.S.
  • 15,970
  • 14
  • 62
  • 86
  • is it possible that i have more than one route ? I mean I am looking for the currently activated in URL (top of browser like : example.com/start ) – Badis Merabet Apr 03 '18 at 14:21
  • @BadisMerabet, yes, it should be possible, I used such code in separated component and got all info that I needed. – P.S. Apr 03 '18 at 14:24
  • 2
    I got this error: ` error TS2339: Property 'filter' does not exist on type 'Observable'. ` – Badis Merabet Apr 03 '18 at 14:31
  • @BadisMerabet, how is it possible? I use very similar code right now and the project is running on my machine with no errors: https://imgur.com/a/hCpdj – P.S. Apr 03 '18 at 14:38
  • Yes, may be I am missing few imports . but the solution of @Tomasz is complete and working. thanks anyway for your effort. – Badis Merabet Apr 03 '18 at 14:54
-1

You can simply do it with an ngIf

In your component ts file

import { Router } from '@angular/router'

constructor(private router: Router)

In your html

<app-navbar *ngIf="!(router.url === '/example')">
</app-navbar>
Manzur Khan
  • 2,366
  • 4
  • 23
  • 44
  • I have tried this but I got `router.url === / ` even that I am on `/start` . are you sure it will work outside `router-outlet` ? – Badis Merabet Apr 03 '18 at 14:28
  • 2
    it has nothing to do with your router-outlet, you are basically fetching the routing state in the app component, given the fact that the app component is always loaded – Manzur Khan Apr 03 '18 at 16:04
  • Staff denied their response, but I gave positive, solved a problem I had that was to know the active route outside the router, when I came from outside the page, as external link. – Chance Jun 18 '19 at 15:36