SebastianG
SebastianG

Reputation: 9594

Angular 10 get router active fragment when scrolling past the fragment?

I'm trying to highlight in the navigation which active fragment you're scrolling past.

Adding the fragment & navigation to the fragment is simple and works well, example:

      class="nav-button unselectable"
      matRipple
      routerLink="/"
      fragment="features"
      [ngClass]="{ 'nav-active': (active_fragment | async) === 'features' }"

But the router obviously can't know which element you're scrolling about so I'm trying to listen on the scroll event and check the nearest element using the Y position.

But my landing page isn't a child of my navigation so the viewchild doesn't work, example:

navigation component:

  @ViewChild('features', { static: false })
  private _features: ElementRef;

  @HostListener('window:scroll', ['$event'])
  private _update_active_fragment(event: any) {
    event.preventDefault();

    console.log(window.pageYOffset);
    console.log(this._features.nativeElement);
  }

Landing page component:

  <app-features #features id="features"></app-features>

But features native element is undefined.

My question is:

Upvotes: 5

Views: 3105

Answers (1)

SebastianG
SebastianG

Reputation: 9594

Made a new navigation service:

public active_fragment: BehaviorSubject<string> = new BehaviorSubject('');

  constructor(private readonly route: ActivatedRoute) {
    this.route.fragment.subscribe((frag) => {
      this.active_fragment.next(frag);
    });
  }

In my navigation component:

      [ngClass]="{
        'nav-active': (navigationService.active_fragment | async) === 'home'
      }"

in my landing component that contains my fragments:

  @ViewChild('features', { read: ElementRef })
  private _features: ElementRef;
  @ViewChild('benefits', { read: ElementRef })
  private _benefits: ElementRef;


  @HostListener('window:scroll', ['$event'])
  private _update_active_fragment(event: any) {
    event.preventDefault();
    switch (true) {
      case window.pageYOffset >=
        this._some_previous_element.nativeElement.offsetTop &&
        window.pageYOffset <= this._features.nativeElement.offsetTop: {
        this.navigationService.active_fragment.next('network-rail-feedback');
        break;
      }

      case window.pageYOffset >= this._features.nativeElement.offsetTop &&
        window.pageYOffset <= this._benefits.nativeElement.offsetTop: {
        this.navigationService.active_fragment.next('features');
        break;
      }


      default:
        break;
    }
  }

Upvotes: 1

Related Questions