Search code examples
javascriptangularjstypescriptangularjs-ng-repeat

Migrating ng-repeat filter to Typescript


My project has been written on AngularJS and now it is migrating to the modern Angular 8.

One of then migration steps is rewrtiting code from Javascript to Typescript. And I have faced a tricky issue with the ng-repeat' filter feature.

What I had. The HTML template:

<div ng-repeat="menuItem in items| filter: vm.filterMenuItem">

It’s a little strange that when calling a function, you don’t need to specify a passed argument.

And the JS code:

function filterMenuItem(menuItem) {
  let paramFits = vm.filters.param === 0 || menuItem.param === vm.filters.param;
  let anotherParamFits = vm.filters.anotherParam === 0 || menuItem.anotherParam === vm.filters.anotherParam;

  return paramFits && anotherParamFits;
 }

Where vm.filters is a controller level variable which can be changed from the template.

Then I rewrited it to the TS:

filterMenuItem(menuItem: MenuItemClass) {
  let paramFits = this.filters.param === 0 || menuItem.param === this.filters.param;
  let anotherParamFits = this.filters.anotherParam === 0 || menuItem.anotherParam === this.filters.anotherParam;

  return paramFits && anotherParamFits;
}

... and it all broke. For some reasons AngularJS not recorgnizes proper controller-lever this inside the function. In this case this is undefined.

Is there any way to keep a custom filter function with the Typescript?


Solution

  • Custom filter function should be modified:

    filterMenuItem(menuItem: MenuItemClass, filters) {
        return menuItem => {
          let paramFits = filters.param === 0 || menuItem.param === filters.param;
          let anotherParamFits = filters.anotherParam === 0 || menuItem.anotherParam === filters.anotherParam;
    
           return paramFits && anotherParamFits;
       }
    }
    

    And the HTML template should be modified like this:

    <div ng-repeat="menuItem in items | filter: vm.filterMenuItem(menuItem, vm.filters)">
    

    The key changes:

    • now we have to say explicitly what the object (menuItem) we want to check with the filter and the filter criteria (vm.filters), and pass it explicitly to the function. And there is no this calls.
    • the filter function have not to simply return a boolean value. It have to return a predicate function with a calcualtion inside it.