angularangular-router

Back click with angular router causing continuous checking triggering of NgFor


Using angular 13, I'm working on a page that has a dashboard of list of tiles for each user project. When the user clicks on the tile, I route to an inbox for that page using a router-outlet. This all works.

When the user clicks the back button from the inbox, however, the page looks ok but showOutlet starts getting hammered along with all the child divs with ngIfs. This isn't killing performance, but it's resulted in a lot of weirdness with clickevents, and it seems suboptimal overall.

I think my question is: what's the best way to handle a back button click?

Here's a simplified version of the code I'm currently using.

<div class="app-wrapper">
    <ng-container>
        <header></header>
        <div class="page" *ngIf="!showOutlet()">
            <!-- Anonymized psuedo-code  -->
            <ng-container  *ngFor="let page of pages">
            (click)="tileClick(tile, request)"

        </div>
        <router-outlet *ngIf="showOutlet"></router-outlet>
    </ng-container>
</div>
public tileClick(tile: ICpTileData, project: projectObj) {
    // tile.route is "/project/[project ID]"
    if (project.StatusCd === 'Sent') {
        if(tile.route) {
            this.showOutlet = true;
                this.router.navigate([tile.route]);        }
                ...
    }
...
}
    public showOutlet(): boolean {
        let routes: string[] = ['page', 'userprofile'];
        for (const r of routes) {
            if (this.router.url.toLowerCase().includes(r)) { 
                return true;
            }
        }
        this.titleService.setTitle('My Events');
        return false;
    }

I've tried making showOutlet a variable rather than a function and setting it to false on a popstateEvent, but I can't find a way to derive the target url from the typescript object, meaning I'd have to assume that any back click would return to the dashboard, which I'd rather not do.


Solution

  • After some messing around I found that the chaos in the DOM was being caused by the ngFor interacting with the ngIf tied to the showOutlet function.

    To solve, I bound the ngIf to a showOutlet variable rather than a function, and had it get set according to route on Init. Also, crucially, I also set the ngFor to a variable loaded on Init (and now a back click), rather than a function. That's probably best practice anyway but it seems pretty important.

    To handle clicking back a bit more elegantly, I make sure that the target url was the dashboard rather than a subroute and then reload all the projects.

        @HostListener('window:popstate', ['$event'])
            onPopState(event: PopStateEvent ) {
                if(location.href.endsWith('/dashboard')){
                    this.showOutlet = false;
                    this.loadingProjects = true;
                    this.loadProjects();
                }  
        }