MarcoLe
MarcoLe

Reputation: 2499

Angular 5 - Routing changes url but doesn't navigate

Currently I have three different modules:

Now in this player search module I have a player search result component with child components. One of the child component is a modal with a list in it. If i click on this list item (player) it should 'navigate' to the parent component and update its view. But the only thing that updates is the url.

There is a workaround with window.location.href(url) that relaods the page after the navigation method updates the url. But I don't like workarounds.

The parent component pretty much looks like:

export class PlayerSearchResultComponent implements OnInit, AfterViewInit {

 public isLoading = true;
  public searchValue: string;
  public playerResult: PlayerByPlayerTagType;
  public hasNoResultFound = false;
  public clanInfo: ClansByClantagType;

  constructor(private playerSearchService: PlayerSearchService,
              private activatedRoute: ActivatedRoute,
              private clanSearchService: ClanSearchService) {
  }

  ngOnInit(): void {
    this.activatedRoute.params.subscribe((params: Params) => {
      this.searchValue = params['playerId'];
    });
  }

  ngAfterViewInit() {
    this.playerSearchService.getPlayerByPlayerTag(this.searchValue).subscribe(player => {
        this.playerResult = player;
        if (!isUndefined(this.playerResult.clan)) {
          this.clanSearchService.getClanByClanTag(this.playerResult.clan.tag).subscribe((data: ClansByClantagType) => {
            this.clanInfo = data;
          });
        }
      }, () => {
        this.hasNoResultFound = true;
        this.isLoading = false;
      },
      () => this.isLoading = false);
  }
}

And the child component:

export class ClanModalComponent {

  @ViewChild('childModal') childModal: ModalDirective;
  @Input() playerResult: PlayerByPlayerTagType;
  @Input() clanInfo: ClansByClantagType;


  constructor(private router: Router) {
  }

  open() {
    this.childModal.show();
  }

  memberSearch(member) {
    this.childModal.hide();
    this.router.navigate(['search/' + member.tag]);
  }

}

The player result module looks like:

const appRoutes: Routes = [
  {path: 'search/:playerId', component: PlayerSearchResultComponent}
];

@NgModule({
  declarations: [
   ...
  ],
  imports: [
    ...
    RouterModule.forChild(
      appRoutes
    )],
  providers: [
     ...
  ],
  exports: []
})
export class PlayerResultModule {
}

Upvotes: 3

Views: 8907

Answers (2)

JWP
JWP

Reputation: 6963

//browser is already on /pathName/oldID, 
//this means our Routes are correct
 
 let newLocation = `/pathName/${newID}`;
 // override default re-use strategy
 this.router
    .routeReuseStrategy
    .shouldReuseRoute = function () {
        return false;
 };
 this.router
   .navigateByUrl(newLocation)
   .then(
   (worked) => {
        //works only because we hooked 
        //the routeReuseStrategy.shouldReuseRoute above
   },
   (error) => {
    debugger;
    }
 );

I've seen this issue more times than I care to admit, it usually is seen when I have a parent container reusing a child component.

  • Parent route is xyz/ by default. Everything loads fine.
  • Parent changes route to xyz/1 to show details of the person id of 1
  • The parent page does nothing but change the url.

This is because Angular's default route reuse strategy will not reload the page!

The code above fixes this default behavior but must be put into the proper component to get the reload from scratch behavior.

Note there are alternatives... Assume you want to maintain the speed of component reuse. In that case just provide an entry point into the already loaded component that resets the data, leaving the component to change via changeDetectorRef.DetectChanges().

Upvotes: 0

David Ibl
David Ibl

Reputation: 911

So, to load based on the route param you have to subscribe to Route params and the load the data. The ngAfterViewInit will not be processed again. Because the component does not load again after route change!

ngOnInit(): void {
    this.activatedRoute.params.subscribe((params: Params) => {
        this.searchValue = params['playerId'];
        this.playerSearchService
            .getPlayerByPlayerTag(this.searchValue)
            .subscribe(player => {
                this.playerResult = player;
                ...
                ...
            });
     }
}

Upvotes: 6

Related Questions