7

I have an issue where my component is re-initializing when I route to it with new parameters. Here are my routes.

const appRoutes: Routes = [
  { path: '', component: MyNewComponentComponent },
  { path: 'tiles', component: DisplayTileData },
  { path: 'tiles/:master/:filters', component: DisplayTileData } 
];

I route to "tiles" and do a service call to fetch some data. I then have a couple of buttons that route back to the same component with values for "master" and "filters". Routing back to the component with parameters re-initializes the component and repeats the service call. I also have a text input on the page. When I first route to this component and add text, the route with parameters is also wiping out that text.

<a *ngFor="let tile of tiles">{{tile.id}}</a><br/><br/>

<input class="form-control" maxlength="30" minlength="3" name="from" ng-reflect-maxlength="30">
<button (click)="addNumberToFilter(15)"></button>
<button (click)="addNewMasterPath('do')">add new Number to Filter</button>

Is there a way to prevent this route re-initialization when routing with new parameters.

I have defaults values for the buttons. Here are the methods.

public variable: any = [3,4];
public master: any = 'eat';

addNewMasterPath(newMasterVariable) {
    this.master = this.master + '-' + newMasterVariable;
    var newMap = this.variable.map(items => { return items}).join('-');
    this.router.navigate(['tiles/', this.master, newMap]);
}

addNumberToFilter(newParameter) {
    this.variable.push(newParameter);
    var newMap = this.variable.map(items => { return items}).join('-');
    this.router.navigate(['tiles/', this.master, newMap]);
}
4
  • Can you post the methods that do the actual setting and mavigation? It looks from the template that the 2 values can be set individually so just curious how you're dealing with that. Commented Jan 16, 2017 at 23:27
  • Possible duplicate of Angular2 - changing location without triggering a Route Commented Jan 17, 2017 at 0:23
  • hmm... right. this.router.navigate(['tiles/', this.master, newMap]); used to work. But am facing the same issues. Go with this.router.navigateByUrl('/team/33/user/11'); which works Commented Jan 17, 2017 at 1:37
  • navigateByUrl has the same behavior. Commented Jan 17, 2017 at 16:24

2 Answers 2

8

Routing back to the component with parameters re-initializes the component and repeats the service call.

That is because the new route where you go is specified as a different route in your application. For the component not to be reinitialized, it has to be the same route.

I see different possibilities here, depending on your specific scenario:

If you only load /tiles to make a service call and then route to tiles/:master/:filters, but /tiles component doesn't make sense without receiving this data, you could consider using a resolver to make the API call, and then having only tiles/:master/:filters route.

From the official docs, you can do the service call inside the resolver:

@Injectable()
export class MasterFiltersResolver implements Resolve<MasterFilter> {
  constructor(private cs: MasterFiltersService, private router: Router) {}
  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Crisis> {
    let id = route.params['id'];
    return this.cs.getData(id).then(data => {
      if (data) {
        return data;
      }
    });
  }
}

Then in your route you can specify it as:

{ path: '', component: MyNewComponentComponent },
{ path: 'tiles/:master/:filters', component: DisplayTileData, 
    resolve: {
        masterFilters: MasterFilterResolver
    } 
} 

This way, it will retrieve the data you need before loading your component.

If your /tiles route component makes sense as a standalone component without master and filters data:

In this case, you can use optional parameters.

When having optional parameters, you would have only this route on your route definition

{ path: '', component: MyNewComponentComponent },
{ path: 'tiles', component: DisplayTileData }

And then navigating to this route through router.navigate('/tiles', {master: '', filter: ''}.

In this case, your component will need something like:

constructor(private route: ActivatedRoute) {}

this.route.params.subscribe(params => {
  // do something
});

this.route.params is an observable of params, so you can be reactive to any change to do async operations.

Sign up to request clarification or add additional context in comments.

1 Comment

We changed up the CustomRouteReuse classes, but more and more cases kept coming up where is did not work out the way we wanted. We ended up using optional parameters.
-1

I used a different approach, listening to the Activated route in my Component

import { ActivatedRoute } from '@angular/router';

constructor(
private route: ActivatedRoute
) {
  this.route.url.subscribe(url =>{
      /* Your function*/
  });
}

1 Comment

What exactly does that accomplish, and how does it solve the issue?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.