hide component in Angular in certain dynamic route

2.9k views Asked by At

I need to hide certain components from my main home page like the navbar and footer when I'm logged in to my admin panel. My admin components are lazy-loaded based on an admin module when called. The necessary components are getting hidden as expected when on admin view if the routes are not dynamic i.e like /admin/login, /admin/dashboard etc. But the problem starts if the routes are dynamic like /admin/category/:categoryId or /admin/user/:userId and in these routes the necessary components like navbar and footer doesn't hide itself. I'm getting the dynamic ids for the routes using ActivatedRoute in the necessary components. Below is the method I'm using on my main page to read the application routes and show/hide components accordingly.

Main.ts

 import { Router, NavigationEnd } from '@angular/router';

  public url: any;

  constructor(private router: Router) {

    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        this.url = event.url;
      }
    })
  }

Main.html

<div class="main__container">
  <app-navbar
    *ngIf="url !== '/admin' && url !== '/admin/dashboard' && url !== '/admin/post-article' && url !== '/admin/video' && url !== '/admin/login' && url !== '/admin/sign-up' && url !== '/admin/category/:categoryId'">
  </app-navbar>
  <app-footer
    *ngIf="url !== '/admin' && url !== '/admin/dashboard' && url !== '/admin/category/:categoryId' && url !== '/admin/post-article' && url !== '/admin/video' && url !== '/admin/login' && url !== '/admin/sign-up'">
  </app-footer>
</div>
2

There are 2 answers

10
Some random IT boy On BEST ANSWER

What you need here is to define regular expressions and test against those. Or maybe it's enough for you to check the string#includes(string) function. I would also suggest to use a more reactive (rxjs like) approach.

On my template I would have:


<div class="main__container">
  <app-navbar *ngIf="canShowNavBar$ | async">
  </app-navbar>
  <app-footer *ngIf="canShowFooter$ | async">
  </app-footer>
</div>

Where on the typescript file I would have:

export class YourComponent implements OnInit {

   canShowNavBar$: Observable<boolean>;
   canShowFooter$: Observable<boolean>;
   navigationEvents$: Observable<NavigationEnd>;


   constructor(private router: Router){}

   ngOnInit() {
     // Like this we define the stream of the NavigationEnd events
     this.navigationEvents$ = this.router.events.pipe(
        filter(event => event instanceof NavigationEnd),
        // This one is not really needed but we're giving some hints to the typescript compiler
        map(event => event as NavigationEnd) 
      );
      // Here we define the stream of booleans that determine whether to show the component or not on your template.
      this.canShowNavBar$ = this.navigationEvents$.pipe(
         map(event => this.shouldShowNavBar(event.url))
      );
      // Because actually you check for the same conditions
      this.canShowFooter$ = this.canShowNavBar$;
   }

   shouldShowNavBar(url: string): boolean {
      // And here you should test against regular expressions:
     switch(true) {
        case /\/admin\/dashboard/.test(url):
        case /\/admin\/category/.test(url):
        // More cases where you should show the navBar
           return true;
        default: return false;
     }



   }
   
}

You can read more about Regular Expressions on JavaScript here

Another approach of implementing the shouldShowNavBar would be using some array predicates like some: Like so:


shouldShowNavBar(url: string): boolean {
   const conditions = [
      !url.startsWith('/admin/dashboard'),
      !url.includes('/admin/category'),
      // More conditions?
   ];
   return conditions.some(isTrue => isTrue);
}

If you don't want to use the async keep your code as it was but do:


<div class="main__container">
  <app-navbar *ngIf="shouldDisplayNavBar(url)">
  </app-navbar>
  <app-footer *ngIf="shouldDisplayNavBar(url)">
  </app-footer>
</div>


shouldShowNavBar(url: string): boolean {
   if(!url) {
     return false;
   }

   const conditions = [
      !url.startsWith('/admin/dashboard'),
      !url.includes('/admin/category'),
      // More conditions?
   ];
   return conditions.some(isTrue => isTrue);
}
2
Rojin Gharooni On

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

@Component({
  selector: 'my-component',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.scss']
})
export class MyComponent implements OnInit {

  constructor(
    private router: Router,
  ) {}

  ngOnInit() {
  }


  /**
   * Check if the router url contains the specified route
   *
   * @param {string} route
   * @returns
   * @memberof MyComponent
   */
  hasRoute(route: string) {
    return this.router.url.includes(route);
  }
}
<!-- First view -->
<div *ngIf="hasRoute('home')">
    First View
</div>

<!-- Second view activated when the route doesn't contain the home route -->
<div *ngIf="!hasRoute('home')">
    Second View
</div>