2016-04-12 25 views
5

コンポーネント内のリストに使用するパイプを渡すことができるコンポーネントを作成しようとしています。私が唯一の解決策をテストし、答えを探しまわってで見つけることができたことのようなものを作成するように見えるから:角2の動的パイプ

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

my-componentテンプレート:

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

正しいパイプロジックにmyFilterをマッピングし、それを実行しますこれはちょっと汚く、最適ではないようです。

私はこれらの行に沿って何かをするAngular 1以来、この問題に対するより良い解決策を考え出しました。

角度2でこれを行うより良い方法はありませんか?

+0

はカスタムフィルタを取得しますか? –

答えて

3

残念ながら私はそうは思わない。これは、あなたが望む動的パイプの文字列を返す関数を持っているangular1と同じです。

ドキュメントを見ても、ドキュメントの表示方法が正確です。

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

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

次にコントローラで:

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

ああ、それは悪いことができます! :)

1

私は何か動作するように管理しましたが、それは少し汚いと悪い(評価付き)ですが、それは私のためのトリックを行います。私の場合は、各行に異なるデータ型のテーブルコンポーネント(タイトル、URL、日付、ステータスなど)があります。私のデータベースでは、ステータスは1enabled)または0disabled)とマークされています。もちろん、私のユーザに有効/無効を表示することがより好ましい。また、私のタイトル欄は多言語で、enまたはidというキーを持つオブジェクトになっています。

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

理想的には、データを自分のアプリのユーザーに表示するには、2つの異なるパイプが必要です。 translateTitlegetStatusのようなものは問題ありません。親のパイプ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] 
    } 
} 

私はおそらくevalの使用について多くの嫌悪感を得るでしょう。それが役に立てば幸い!

更新:あなたがそれを必要とするかもしれないとき

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> 

が返されます:

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

これに対処する最も簡単な方法は、HTMLテンプレートでパイプを使用しないためにも、代わりに、注入しますパイプをコンポーネントのコンストラクタに挿入し(DIを使用して)、変換を機能的に適用します。これは、Observableマップや同様のrxjsストリームではうまくいきます。

+0

良い提案ですが、もしそれが私の望むように使われるなら、それはまだラッパーサービスを必要とします。 – Chrillewoodz

2

borislemkeの答えのビルは、ここeval()を必要としている私はむしろきれい見つからない解決策です:

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 = []; 
}