Home > database >  Can we select <a> element when it's routerLink is active in angular?
Can we select <a> element when it's routerLink is active in angular?

Time:03-21

I want to select <a> element by className when its router link is active, but it returns null

navbar.component.html code:

<nav >
  <ul>
    <li >
      <a
        [routerLink]="['/app/profile', username, 'posts']"
        routerLinkActive="active-link"
        >Posts</a
      >
    </li>
    <li >
      <a
        [routerLink]="['/app/profile', username, 'images']"
        routerLinkActive="active-link"
        >Images</a
      >
    </li>
  </ul>
</nav>

navbar.component.ts code:

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

@Component({
  selector: 'profile-navbar',
  templateUrl: './navbar.component.html',
  styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit, AfterViewInit {
  
  constructor() { 
  }
  
  ngOnInit(): void {
  }
  
  ngAfterViewInit(): void {
    const activeLink = document.querySelector('.active-link');
    console.log(activeLink)
  }

}

How can I select the element the element based on routerLinkActive class??

CodePudding user response:

You can't use this LifeCycleHook try ngAfterViewChecked() instead or listen to the route changes (How to detect a route change in Angular?) and do your selection based on the event or even better just use in your .css file:

a.active {
/* your style */
}

If you just want to style it, there is usually no need to select it, but in your case with the calculation of translate3d and scaleX I'm not sure...

CodePudding user response:

To get a series of "divs" you can use a template reference variable and ViewChildren. When you has ViewChildren you can find the element with a class or anopther property.

Case of routerLinks the approach is similar, but you can to have in ViewChildren the [routerLinksActive seeing as "ElementRef" and seeing as "RouterLinkActive"

Some like

  //links are the "RouterLinkActive"
  @ViewChildren(RouterLinkActive) links:QueryList<RouterLinkActive>
  
  //lisk are the "RouterLinkAvtive" but seeing as ElementRef
  @ViewChildren(RouterLinkActive,{read:ElementRef}) linksElements:QueryList<ElementRef>
  @ViewChild('indicator') indicator:ElementRef
  constructor(private router: Router) {}
  ngOnInit() {
    this.router.events.pipe(
       filter(x=>x instanceof NavigationEnd),
       startWith(null)).subscribe(res=>{

      //we need enclosed in a setTimeout because when the event NavigationEnd
      //happens, Angular are not add the class "active-links"
      // nor link isActive=true
      setTimeout(()=>{

        //first find the "index" in the QueryList
        const index=(this.links.map(
          (x:RouterLinkActive,i:number)=>({isActive:x.isActive,index:i}))          
          .find(x=>x.isActive) || {index:-1}).index
  
        //it's the same index in the ElementRef
        if (index>=0)
        {
          const el=this.linksElements.find((_,i)=>i==index)
          
          //We use the "el" to change the style.top of the indicator
           this.indicator.nativeElement.style.top=
                       el.nativeElement.offsetTop 'px'
        }
        else
        {
          this.indicator.nativeElement.style.top='-100px'
        }
      })
    })
  }

Where

<nav >
<ul>
  <li >
    <a
      [routerLink]="['/hello']"
      routerLinkActive="active-link"
      >Posts</a
    >
  </li>
  <li >
    <a
      [routerLink]="['/by']"
      routerLinkActive="active-link"
      >Images</a
    >
  </li>
</ul>
<div #indicator ></div>
</nav>

like is showed in this stackblitz

  • Related