Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 exact RouterLinkActive including fragments?

When using routerLink and routerLinkActive to apply CSS to a navigation bar, I'd like to also include the fragment information so that links are unique for sections within a homepage.

I've tried using [routerLinkActiveOptions]="{ exact: true }" wihtout any luck.

The relevant part of the navigation bar code is:

  <li routerLinkActive="active"
      [routerLinkActiveOptions]="{ exact: true }">
    <a routerLink="/sitio" fragment="inicio">Inicio</a>
  </li>
  <li routerLinkActive="active"
      [routerLinkActiveOptions]="{ exact: true }">
    <a routerLink="/sitio" fragment="invierte">Invierte</a>
  </li>
  <li routerLinkActive="active"
      [routerLinkActiveOptions]="{ exact: true }">
    <a routerLink="/sitio" fragment="contacto">Contacto</a>
  </li>

The three different URLs the above code visits are:

  • /sitio#inicio
  • /sitio#invierte
  • /sitio#contacto

But when clickin any of them, all of them are marked as being active (because they correspond to the routerLink="/sitio" and the fragment=* information is not included in the check. This results in the navigation bar looking like this when clicking on any of them:

enter image description here

Any ideas on how to do this?

like image 500
Omar Trejo Avatar asked Dec 30 '16 09:12

Omar Trejo


People also ask

How do I know if my routerLink is active?

routerLinkActive is simply an indicator of whether this link represents the active route. @jessepinho - Tried it - [routerLinkActive]="'active'" will only work if you also have [routerLink] in the a-tag. If you had (click)="navitageTo('/route')" instead of [routerLink], and in that function, you called this.

What is routerLinkActive in angular?

RouterLinkActivelinkTracks whether the linked route of an element is currently active, and allows you to specify one or more CSS classes to add to the element when the linked route is active.

How do I set my router to active links?

Create the header component that contains the navigation links. Then apply the “routerLinkActive” on each router link and provide the CSS class to this property. Here we have created the “active” class in CSS file. Provide the { exact : true } to the root route to avoid multiple active router links.

Can we pass object in routerLink?

RouterLink for dynamic dataDynamic data or user-defined objects can be passed from Angular version 7.2 using the state object stored in History API. The state value can be provided using the routerLink directive or navigateByURL.


1 Answers

I just thought I would put how I solved it in case someone runs into the same problem: keep track of the current section in the site and use a class binding through a function in the component instead of using routerLinkActive.

The links in the template become:

<li [class.active]="isSectionActive('inicio')">
    <a routerLink="/sitio" fragment="inicio">Inicio</a>
</li>
<li [class.active]="isSectionActive('invierte')">
    <a routerLink="/sitio" fragment="invierte">Invierte</a>
</li>
<li [class.active]="isSectionActive('contacto')">
    <a routerLink="/sitio" fragment="contacto">Contacto</a>
</li>

Note the lack of use of routerLinkActive, and the use of class binding [class.active]=isSectionActive('<name-of-section>') instead.

The code that keeps track of the section we're inside of and decides whether or not to apply the CSS class in the template is:

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

// Class signature... {

    private activeSiteSection: string;

    constructor(
        private router: Router,
        private sessionService: SessionService
    ) {
        router.events.subscribe((event) => {
            if(event instanceof NavigationEnd ) {
                this.SiteURLActiveCheck(event);
            }
        });
    }

    private SiteURLActiveCheck(event: NavigationEnd): void {
        if (event.url.indexOf('#inicio') !== -1) {
            this.activeSiteSection = 'inicio';
        } else if (event.url.indexOf('#invierte') !== -1) {
            this.activeSiteSection = 'invierte';
        } else if (event.url.indexOf('#contacto') !== -1) {
            this.activeSiteSection = 'contacto';
        } else {
            this.activeSiteSection = '';
        }
    }

    private isSectionActive(section: string): boolean {
        return section === this.activeSiteSection;
    }
}

Probably overkill but I rather go this route than modify Angular 2's source. :)

like image 54
Omar Trejo Avatar answered Sep 30 '22 20:09

Omar Trejo