Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

May 27, 2016

Angular 2: Filtering a List Using a Computed Property and ngModelChanged

Filed under: Angular @ 4:43 pm
Tags: , , ,

In my Pluralsight course: “Angular 2: Getting Started”, I demonstrate how to filter a list of products for display using a custom pipe. However, using a custom pipe does not provide easy access to the filtered result. For example, say you also want the count of the filtered list so you can display “5 of 125” or access other information about the list. In these cases, it is best to filter without using a custom pipe. This post shows you one technique: using a computed property and the ngModelChanged event.

Additional techniques for solving this problem are:

This post updates the code available from my github repo. So starting with that code:

1. Change the declarations adding a productsFiltered computed property. The productsFiltered property will contain the filtered list of products.

pageTitle: string = ‘Product List’;
imageWidth: number = 50;
imageMargin: number = 2;
showImage: boolean = false;
listFilter: string;
errorMessage: string;
products: IProduct[];
productsFiltered: IProduct[];

2. Add an onFilterChanged event handler that executes each time the filter input box is changed:

onFilterChanged(filter: any) { 
    this.listFilter = filter;
    filter = filter ? filter.toLocaleLowerCase() : null;
    this.productsFiltered = filter ? this.products.filter((product: IProduct) =>
        product.productName.toLocaleLowerCase().indexOf(filter) !== -1) : this.products;
}

This code sets the listFilter property and re-filters the list every time the listFilter input box changes. (Recall that we’ve removed the two-way binding, so we need to manually set the listFilter property.)

This is not enough, however. When the page is first displayed the product array is empty so nothing appears on the page. We need to initialize the computed property when the product data is retrieved.

3. One way to set the computed property when the data is retrieved is to modify the ngOnInit() method as follows:

ngOnInit(): void {
       this._productService.getProducts()
                 .subscribe(
                   products => this.onProductsRetrieved(products),
                   error =>  this.errorMessage = <any>error);
}

When the products are retrieved, this code calls the onProductsRetrieved method.

4. Create the new onProductsRetrieved method as follows:

onProductsRetrieved(products: IProduct[]) {
     this.products = products;
    this.productsFiltered = products;

}

This code sets the retrieved products to our product property and initializes our computed property.

5. The only other changes are to the template:

<input type=’text’ (ngModelChange)=’onFilterChanged($event)’ [ngModel]=’listFilter’ />

This separates the two-way binding into its one-way property binding with the [ngModel] and the one-way event binding with (ngModelChange). Whenever the model changes, the onFilterChanged method is called.

6. And change the template binding:

<tr *ngFor=’let product of productsFiltered‘>

This now binds to the productsFiltered property and no longer needs the pipe. We can then also bind other elements to this property or this property’s count method as needed.

Enjoy!

4 Comments

  1.   Robert Polevoi — July 15, 2016 @ 2:52 pm    Reply

    Real useful Deborah.

    Just a couple of questions — applicable to the whole project

    1. Don’t understand why a Router is injected into ProductListComponent. Don’t see where it is used.

    2. The stars component doesn’t display properly for me at a width of 86 pixels. (It wraps around). Seems to work fine with a larger width.

    Thanks for the insights.

    •   deborahk — July 18, 2016 @ 2:54 pm    Reply

      Thanks!
      1. This looks “left over” from something else. You should be able to remove it.
      2. This may be an issue with screen resolution. The purpose of this component was to show how to do a nested component and does not show the best way to build the UI. 🙂

  2.   Muhammad Sami — September 28, 2016 @ 2:08 pm    Reply

    After finishing your Angular 2 pluralSight course. You are just “awesome”

    •   deborahk — October 19, 2016 @ 9:15 am    Reply

      Thank you so much!

Trackbacks/Pingbacks

  1. Angular 2: Filtering a List Using a Computed Property and Events -Deborah's Developer MindScape
  2. Angular 2: Filtering a List Using a Computed Property and Setter -Deborah's Developer MindScape

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2019 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs