[Fixed] Back to top of a ngIf section

Issue

I have an Angular SPA, page contains either listing of records or edit a record section (includes history of editing as well). Initial state is to show list of records.

Because some record has long history of editing, so placing a Back to top of Editing will make it easier to use. HTML5 supports #top, right? Well, it actually toggles back to non-editing mode shows list of records 🙁

HTML below:

<div *ngIf="editMode">
  <a id="top"></a>
  record detailed content here
  <hr>
  long history of record editing here
  <a href="#top">Back to top of Editing</a><!-- Nope, it actually toggles back to non-editing mode shows list of records -->
<div>
 
<div *ngIf="!editMode">
  <mat-card *ngFor="let rec of listRec">
  ...
  <input type=button (click)="switchToEditMode()">Edit</input>
  </mat-card>
</div>

.TS:

editMode: boolean = false;
...
switchToEditMode() { editMode=true; ...}

Update, this is how it works following @RedJandal suggestion using Manual Scrolling, add this to HTML

<span #myTop id="myTop"></span>
<button (click)="toMyTop()">go to Top</button>

add this to TS

@ViewChild("myTop") myTop: ElementRef;
toMyTop()
  {
    const targetElement = this.myTop.nativeElement;
    targetElement.scrollIntoView({behavior: "smooth"});
  }

Note, to use <a> in place of <button>, important to remove href=#<anything>

Solution

Because you are using an anchor tag the page is being refreshed, that is why it toggles back to non-editing mode.

Automatic Scrolling

Since Angular v6, there is the new anchorScrolling option for the RouterModule. You can set it in the module’s import:

imports: [
  ...,
  RouterModule.forRoot(routes, {anchorScrolling: 'enabled'})

With this, Angular will automatically scroll to the element with the id of the given fragment.

⚠️ However, this does not work when the data is loaded asynchronously, see this Github issue. ⚠️


Manual Scrolling

Smooth scrolling is not yet possible via the RouterModule, but you can do it manually:

Get your target e.g. with ViewChild:

@ViewChild('pageInfo') pageInfo: ElementRef; 

Call scrollIntoView on the nativeElement:

const targetElement = this.pageInfo.nativeElement
targetElement.scrollIntoView({behavior: "smooth"})

Leave a Reply

(*) Required, Your email will not be published