3

I would like to create a custom pipe in angular 4.x that takes a predicate function as parameter in order to filter values from an array.

Here is the code of my pipe : [Snippet #1 : mypipe.ts]

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
  name: 'filter'
})
export class FilterPipe implements PipeTransform {
  transform(values: any[], predicate: (any) => boolean): any {
    return values.filter(predicate);
  }
}

Here is how I use it in my template : [Snippet #2 : mycomponent.html]

<div *ngFor="let item of (items | filter:(x=>x.isValid))">

But at runtime, I get this error : [Snippet #3]

Error: Uncaught (in promise): Error: Template parse errors:
Parser Error: Bindings cannot contain assignments at column 44 in [let item of (items | filter:(x=>x.isValid))]

I solved this by creating an isValid() function in my component and using this function as an argument of my filter :

[Snippet #4 : mycomponent.ts]

isItemValid(item): boolean {
  return item.isValid;
}

[Snippet #5 : mycomponent.html]

<div *ngFor="let item of (items | filter:isItemValid)">

But I don't really like this option because I think it's less readable than with an arrow function (you have to switch to the component.ts file to understand what will be filtered in component.html).

Is there a better solution that would look like the snippet #2 ?

Dartz
  • 165
  • 12

1 Answers1

1

There is not a better solution. Angular's parser doesn't support declaring methods like that as part of any binding -- presumably so that people don't write large functions in their templates, as the controller is suppose to hold that logic.

I think this use case is closer to a gray area than most, but Angular is opinionated enough in this regard that they won't let you try.

See this for more information: Angular 2 - Bindings cannot contain assignments

Community
  • 1
  • 1
chrispy
  • 3,552
  • 1
  • 11
  • 19