I have a component that display the result of an API query. I want to add a dropdown box so the list can be filtered but I can't seem to get the page to reload when the url query parameters change.
<div>
<H2>Products</H2>
<form>
Filter By Manufacturer
<select (change)="onManufacturerChange($event.target.value)">
<option value="">All</option>
<option [value]="m" *ngFor="let m of manufacturers">{{m}}</option>
</select>
</form>
<ul>
<li *ngFor="let p of products"><B>{{p.manufacturer}}</B> - {{p.name}}</li>
</ul>
</div>
And the Typescript
export class ProductListComponent implements OnInit {
public products: Array<object> = [];
public manufacturers: any = [];
public manufacturer: string = "";
public search: string = "";
constructor(private _assetService: AssetService, private router: Router, private route: ActivatedRoute) { }
ngOnInit() {
this.route.queryParams.subscribe(params => {
console.log(params);
if('manufacturer' in params){
this.manufacturer = params.manufacturer;
}
if('search' in params){
this.search = params.search;
}
})
this._assetService.getManufacturers().subscribe(data => {
this.manufacturers = data;
})
this.loadProducts();
}
loadProducts(){
this._assetService.getProducts(this.manufacturer,this.search).subscribe((data: ProductListResult) => {
this.products = data.products;
})
}
onManufacturerChange(newValue){
this.router.navigate(['/products'], {queryParams: {manufacturer: newValue}});
}
}
When I change the item selected in the drop down box the URL displayed in the browser changes but the page does not reload. If I refresh the browser manually with the desired URL the correct output is shown. If I change the path in route.navigate to a totally different route that works correctly. If I add a call to loadProducts()
after router navigate some it reloads the page but one selection out of phase.
Everything I've read says that if the array referenced in ngFor changes it should automagically update the DOM but I can't seem to trigger it. Do I need to call some sort of refresh or invalidate routine to update the DOM? Do I need to set something in the router to recognize changes to the query parameters? Am I going about this all wrong?
As far as I can tell there is no elegant way to get Angular to reload the page when the query parameters change.
The error in my code is that loadProducts() uses this.manufacturer so I need to set that in onManufacturerChange(). It doesn't reload the page but it does reload the data and update the DOM.
Then I need to create an updateRoute() function that is called after subscribe has loaded the data from the api. The Back and Forward buttons in the browser still don't work (it steps through the URLs but doesn't update the display) but the URL and the display otherwise stay in sync. Close enough for now.
loadProducts() {
this._assetService.getProducts(this.manufacturer,this.search).subscribe((data: ProductListResult) => {
this.products = data.products;
this.updateRoute();
})
}
onManufacturerChange(newValue){
this.manufacturer = newValue;
this.loadProducts();
}
updateRoute( ){
var queryParams = {};
if (this.manufacturer!= "" ){queryParams['manufacturer'] = this.manufacturer;}
if (this.search!= "" ){queryParams['manufacturer'] = this.search;}
this.router.navigate(['/products'], {queryParams: queryParams});
}