I'm trying to create a component where you can pass which pipe that should be used for a list inside the component. From what I could find by testing and looking around for answers the only solution appears to create something like:
<my-component myFilter="sortByProperty"></my-component>
my-component
template:
<li *ngFor="#item of list | getPipe:myFilter"></li>
Which then maps myFilter
to the correct pipe logic and runs it, but this seems a bit dirty and not optimal.
I thought they would have come up with a better solution to this problem since Angular 1 where you would also do something along these lines.
Is there not a better way to do this in Angular 2?
These filters are known as "Pipes" in Angular 2. Pipes allow us to change the data inside the template. Normally, a pipe takes the data and transforms this input to the desired output. There are many built-in pipes in Angular 2.
Use pipes to transform strings, currency amounts, dates, and other data for display. Pipes are simple functions to use in template expressions to accept an input value and return a transformed value. Pipes are useful because you can use them throughout your application, while only declaring each pipe once.
A pure pipe is only called when Angular detects a change in the value or the parameters passed to a pipe. An impure pipe is called for every change detection cycle no matter whether the value or parameter(s) changes.
Building on borislemke's answer, here's a solution which does not need eval()
and which I find rather clean:
dynamic.pipe.ts:
import { Injector, Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'dynamicPipe' }) export class DynamicPipe implements PipeTransform { public constructor(private injector: Injector) { } transform(value: any, pipeToken: any, pipeArgs: any[]): any { if (!pipeToken) { return value; } else { let pipe = this.injector.get(pipeToken); return pipe.transform(value, ...pipeArgs); } } }
app.module.ts:
// … import { DynamicPipe } from './dynamic.pipe'; @NgModule({ declarations: [ // … DynamicPipe, ], imports: [ // … ], providers: [ // list all pipes you would like to use PercentPipe, ], bootstrap: [AppComponent] }) export class AppModule { }
app.component.ts:
import { Component, OnInit } from '@angular/core'; import { PercentPipe } from '@angular/common'; @Component({ selector: 'app-root', template: ` The following should be a percentage: {{ myPercentage | dynamicPipe: myPipe:myPipeArgs }} `, providers: [] }) export class AppComponent implements OnInit { myPercentage = 0.5; myPipe = PercentPipe; myPipeArgs = []; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With