Issue
I want to select <a>
element by className when its router link is active, but it returns null
navbar.component.html code:
<nav class="profile-navbar">
<ul>
<li class="posts-item">
<a
[routerLink]="['/app/profile', username, 'posts']"
routerLinkActive="active-link"
>Posts</a
>
</li>
<li class="images-item">
<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??
Solution
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 class="profile-navbar">
<ul>
<li class="posts-item">
<a
[routerLink]="['/hello']"
routerLinkActive="active-link"
>Posts</a
>
</li>
<li class="images-item">
<a
[routerLink]="['/by']"
routerLinkActive="active-link"
>Images</a
>
</li>
</ul>
<div #indicator class="indicator"></div>
</nav>
like is showed in this stackblitz
Answered By - Eliseo
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.