Dynamic pipe in Angular 2

I am trying to create a component in which you can pass the channel that should be used for the list inside the component. From what I could find by testing and looking back at the answers, the only solution seems to create something like:

<my-component myFilter="sortByProperty"></my-component> 

my-component :

 <li *ngFor="#item of list | getPipe:myFilter"></li> 

Which then maps myFilter to the correct channel logic and runs it, but it seems a bit dirty and not optimal.

I thought they came up with a better solution to this problem, since Angular 1, where you will also be doing something in this direction.

Is there a better way to do this in Angular 2?

+5
source share
4 answers

Unfortunately, I don’t think so. This is the same as in corner1, where you have a function that returns a string for the dynamic pipe that you want.

A look at documents that show exactly how they show it.

https://angular.io/docs/ts/latest/guide/pipes.html

 template: ` <p>The hero birthday is {{ birthday | date:format }}</p> <button (click)="toggleFormat()">Toggle Format</button> ` 

Then in the controller:

 get format() { return this.toggle ? 'shortDate' : 'fullDate'} 

Alas, it could be worse! :)

+3
source

I managed to get something working, it's a little dirty and spiteful (with eval), but it does the trick for me. In my case, I have a table component with different types of data in each row (e.g. name, URL, date, status). In my database, status is marked as 1 as enabled or 0 for disabled . Of course, it’s preferable to show my user on / off. In addition, my column header is multilingual, which makes it an object with en or id as the key.

 // Example row object: title: { "en": "Some title in English", "id": "Some title in Indonesian" }, status: 1 // either 1 or 0 

Ideally, I need 2 different channels to convert my data to show my user applications. Something like translateTitle and getStatus would be fine. Let the parent channel dynamicPipe .

 /// some-view.html {{ title | dynamicPipe:'translateTitle' }} {{ status | dynamicPipe:'getStatus' }} /// dynamic.pipe.ts //...import Pipe and PipeTransform @Pipe({name:'dynamicPipe'}) export class DynamicPipe implements PipeTransform { transform(value:string, modifier:string) { if (!modifier) return value; return eval('this.' + modifier + '(' + value + ')') } getStatus(value:string|number):string { return value ? 'enabled' : 'disabled' } translateTitle(value:TitleObject):string { // defaultSystemLanguage is set to English by default return value[defaultSystemLanguage] } } 

I probably get a lot of hate for using eval. Hope this helps!

Update: if you may need

 posts = { content: [ { title: { en: "Some post title in English", es: "Some post title in Spanish" }, url: "a-beautiful-post", created_at: "2016-05-15 12:21:38", status: 1 }, { title: { en: "Some post title in English 2", es: "Some post title in Spanish 2" }, url: "a-beautiful-post-2", created_at: "2016-05-13 17:53:08", status: 0 } ], pipes: ['translateTitle', null, 'humanizeDate', 'getStatus'] } <table> <tr *ngFor="let row in posts"> <td *ngFor="let column in row; let i = index">{{ column | dynamicPipe:pipes[i] }}</td> </tr> </table> 

Will return:

 | title | url | date | status | | Some post t... a-beautiful... an hour ago enabled | Some post ...2 a-beautifu...2 2 days ago disabled 
+2
source

The easiest way to handle this is not to use pipes in HTML templates, but instead to insert a pipe into the component constructor (using DI), and then apply the transformation functionally. This works well with Observable maps or similar rxjs streams.

+2
source

Based on borislemke's answer, here is a solution that does not need eval() and which I find pretty 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 = []; } 
+2
source

Source: https://habr.com/ru/post/1246912/


All Articles