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]);
}
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.
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*/
});
}