Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 routing with fragments, async data

I am building a site that includes one home page of many sections and two additional pages. Each section is its own component. The bottom section, contact, should be accessible via an anchor link. I have successfully been able to anchor to the contact section while on the home page. When routing to "contact" from a different page, however, I am encountering a timing issue. When I increase the SetTimeOut parameters to 2s instead of 1s, the function works properly. However, this is a hacky solution.

I know that routing with fragments is still buggy in Angular. Could anyone tell me the best way to approach this? I believe that the data loading is slowing the ability to find the anchor when I'm routing to the homepage#contact from the project or press page.

I have tried ng2-page-scroll, as well as tracked this thread: https://github.com/angular/angular/issues/6595 and tried most of the proposed solutions. Nothing is allowing me to navigate to the contact section on the home page from a different page WITHOUT at least a 2s SetTimeOut.

This is in my home component, which contains the contact component.

  ngAfterViewInit(){
  this._route.fragment
    .subscribe(
      (fragment: string) => {
        console.log('is there a fragment?');
        console.log(fragment);
        const element = document.querySelector("#" + fragment)
        if (element) {element.scrollIntoView(); console.log(element);}
        else { console.log('no element i guess '); }
        // if (fragment){
        //   this.scrollToAnchor(fragment, 1000);
        // }
      }
    );
  }

This is my nav markup:

<li class="nav-li">
   <a
     [routerLink]="['/']"
     fragment="contact"
     class="nav-a"
     (click)="_globalService.toggleNav()">
     contact
   </a>
</li>

This is my HomeComponent, which contains the contact section:

<div class="homeWrap" id="container">
  <app-splash-graphic id="splash" name="splash"></app-splash-graphic>
  <app-about id="about" name="about"></app-about>
  <app-projects></app-projects>
  <app-press></app-press>
  <div id="contact" name="contact">
      <app-contact></app-contact>
  </div>
</div>

I'm really at a loss! Any wisdom greatly appreciated.

like image 756
Waverly Avatar asked Feb 06 '26 22:02

Waverly


1 Answers

I have created a directive for simular situation:

/**
 * directive that causes the browser to scroll and focus to the anchor from the latest activated route fragment
 * usage:
 * link with fragment: <a tabindex="0" [routerLink]="['/']" fragment="contact">
 * html in / route page:
 * <section appFocusFragment>
 *  <a id="contact">First focused content after load</a>
 */
import { Directive, AfterViewInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Directive({
  selector: '[appFocusFragment]'
})
export class FocusFragmentDirective implements AfterViewInit  {
  private fragment: string;
  constructor(private route: ActivatedRoute) {
    // be sure the navigation goes to the # fragment
    this.route.fragment.subscribe(fragment => { this.fragment = fragment; });
  }

  ngAfterViewInit(): void {
    try {
      const anchor = document.querySelector<HTMLAnchorElement>('#' + this.fragment);
      anchor.focus();
      anchor.scrollIntoView();
    } catch (e) { }
  }
}
like image 98
Ron Jonk Avatar answered Feb 09 '26 07:02

Ron Jonk