パイプ ''が見つかりませんでしたangular2カスタムパイプ


105

このエラーを修正できないようです。検索バーとngForがあります。私はこのようなカスタムパイプを使用して配列をフィルタリングしようとしています:

import { Pipe, PipeTransform } from '@angular/core';

import { User } from '../user/user';

@Pipe({
  name: 'usersPipe',
  pure: false
})
export class UsersPipe implements PipeTransform {
  transform(users: User [], searchTerm: string) {
    return users.filter(user => user.name.indexOf(searchTerm) !== -1);
  }
}

使用法:

<input [(ngModel)]="searchTerm" type="text" placeholder="Search users">

<div *ngFor="let user of (users | usersPipe:searchTerm)">
...
</div>

エラー:

zone.js:478 Unhandled Promise rejection: Template parse errors:
The pipe 'usersPipe' could not be found ("
<div class="row">
    <div  
    [ERROR ->]*ngFor="let user of (user | usersPipe:searchTerm)">

角度バージョン:

"@angular/common": "2.0.0-rc.5",
"@angular/compiler": "2.0.0-rc.5",
"@angular/core": "2.0.0-rc.5",
"@angular/platform-browser": "2.0.0-rc.5",
"@angular/platform-browser-dynamic": "2.0.0-rc.5",
"@angular/router": "3.0.0-rc.1",
"@angular/forms": "0.3.0",
"@angular/http": "2.0.0-rc.5",
"es6-shim": "^0.35.0",
"reflect-metadata": "0.1.3",
"rxjs": "5.0.0-beta.6",
"systemjs": "0.19.26",
"bootstrap": "^3.3.6",
"zone.js": "^0.6.12"

1
コンポーネントのパイプに含めましたか?
ハリーニン2016

それが理由だと気づきました。カスタムパイプの角度の例がこれを行わない理由
Sumama Waheed

彼らはそれをグローバルパイプとして定義しました。多くの場所で使用していて、すべての単一のアノテーションで定義したくない場合は、カスタムパイプに同じことを行うことができます。
ハリー・ニン

@SumamaWaheed私はそれがドキュメントのどこかの時点にあったと確信していますが、ドキュメントは今それを言及/表示していません。
ミケランジェロ

回答:


144

「クロスモジュール」の問題に直面ていないことを確認してください

パイプを使用しているコンポーネントが、パイプコンポーネントを「グローバルに」宣言したモジュールに属していない場合、パイプが見つからず、このエラーメッセージが表示されます。

私の場合、別のモジュールでパイプを宣言し、そのパイプを使用するコンポーネントを持つ他のモジュールにこのパイプモジュールをインポートしました。

パイプを使用しているコンポーネントが

パイプモジュール

 import { NgModule }      from '@angular/core';
 import { myDateFormat }          from '../directives/myDateFormat';

 @NgModule({
     imports:        [],
     declarations:   [myDateFormat],
     exports:        [myDateFormat],
 })

 export class PipeModule {

   static forRoot() {
      return {
          ngModule: PipeModule,
          providers: [],
      };
   }
 } 

別のモジュール(app.moduleなど)での使用

  // Import APPLICATION MODULES
  ...
  import { PipeModule }    from './tools/PipeModule';

  @NgModule({
     imports: [
    ...
    , PipeModule.forRoot()
    ....
  ],

6
この解決策が私にとって有効な唯一の解決策でした。パイプにはモジュールが必要であることが判明
AJ Zane

私もこれを見つけて、NG 2.8のパイプが見つからないというエラーを部分的に解決しました。さらに、使用中の命名規則のみに関連するtypescriptの「警告」がありました。テンプレート内。
CNSKnight 2017

これは本当に私にとって有効な唯一の解決策です!共有モジュール全体を試してみましたが、このソリューションは魅力的に機能しました。@Karlありがとうございます!
lulu88 2017年

コンポーネントテストでこれをどのようにテストするか
apoorva '20

2
ありがとう!私の問題は、「exports:[myPipe]」がモジュール用のエクスポートであると思っていなかったことです。
Rafique Mohammed

55

パイプをモジュール宣言に含める必要があります。

declarations: [ UsersPipe ],
providers: [UsersPipe]

5
ただのメモですが、最初はパイプをプロバイダーに含めただけです。これは、モジュールファイルの宣言とプロバイダーの両方に含める必要があります。
Greg A

私はあなたの提案に従うまで苦労していました。私はそれを理解するために約4時間を無駄にしました。提案ありがとうございます。
user1501382 2017

5
なぜこれが文書化されていないのですか?ドキュメントの状態You must include your pipe in the declarations array of the AppModule.angular.io/guide/pipes。とにかく、あなたの答えは私の問題も解決します。
Martijn 2017年

ありがとう、Yuvals。詳細を追加します:パイプが必要なモジュールの宣言。
Vinicios Torres 2017

5
exports: [UsersPipe]モジュールが他のモジュールによってインポートされる場合も含めることを忘れないでください。
Precastic 2018年

18

Ionicの場合、@ Karlが言及したように複数の問題に直面する可能性があります。イオンの遅延読み込みページで問題なく機能するソリューションは次のとおりです。

  1. 次のファイルでpipesディレクトリを作成します:pipes.tsおよびpipes.module.ts

// pipes.tsコンテンツ(内部に複数のパイプを含めることができます。

use @Pipe function before each class)
import { PipeTransform, Pipe } from "@angular/core";
@Pipe({ name: "toArray" })
export class toArrayPipe implements PipeTransform {
  transform(value, args: string[]): any {
    if (!value) return value;
    let keys = [];
    for (let key in value) {
      keys.push({ key: key, value: value[key] });
    }
    return keys;
  }
}

// pipes.module.ts content

import { NgModule } from "@angular/core";
import { IonicModule } from "ionic-angular";
import { toArrayPipe } from "./pipes";

@NgModule({
  declarations: [toArrayPipe],
  imports: [IonicModule],
  exports: [toArrayPipe]
})
export class PipesModule {}
  1. PipesModuleをapp.moduleと@NgModule importsセクションに含める

    import { PipesModule } from "../pipes/pipes.module"; @NgModule({ imports: [ PipesModule ] });

  2. カスタムパイプを使用する各.module.tsにPipesModuleを含めます。インポートセクションに追加することを忘れないでください。//例。ファイル:pages / my-custom-page / my-custom-page.module.ts

    import { PipesModule } from "../../pipes/pipes.module"; @NgModule({ imports: [ PipesModule ] })

  3. それでおしまい。これで、テンプレートでカスタムパイプを使用できます。例

<div *ngFor="let prop of myObject | toArray">{{ prop.key }}</div>


これはイオンの命の恩人でした、ありがとう。「ionic generate pipe ....」では、pipes.module.tsの作成など、必要なすべてのステップが生成されるわけではないためです。あなたのアプローチは完璧に機能しました。ionic v4では、インポートパスにいくつかの小さな変更が必要です。
royappa

1
app.module.tsのインポートは必要ないので、そのステップは省略できます。「共有モジュール」が必要な他のモジュールにインポートされているためです。app.moduleのインポートがグローバルに機能すればいいのですが、試してみましたが機能しません。
royappa

私はまだこれに直面しています:CONSOLE ERROR file:node_modules/@angular/core/fesm5/core.js:4002:0 ERROR Error:Uncaught(in promise):NullInjectorError:StaticInjectorError(AppModule)[ToHtmlPipe-> DomSanitizer]:StaticInjectorError (プラットフォーム:コア)[ToHtmlPipe-> DomSanitizer]:NullInjectorError:DomSanitizerのプロバイダーがありません!
mircobabini

12

上記の「クロスモジュール」の回答は私の状況に非常に役立ちましたが、考慮すべき別のしわがあるので、それについてさらに詳しく説明します。サブモジュールがある場合、テストでは親モジュールのパイプも表示されません。そのため、パイプを独自の別のモジュールに配置する必要がある場合もあります。

以下は、サブモジュールに表示されないパイプに対処するために実行した手順の概要です。

  1. (親)SharedModuleからパイプを取り出し、PipeModuleに入れる
  2. SharedModuleで、PipeModuleをインポートしてエクスポートします(SharedModule依存するアプリの他の部分が自動的にPipeModuleにアクセスするため)
  3. Sub-SharedModuleの場合は、PipeModuleをインポートします。これにより、他の問題の中で循環依存の問題が発生するSharedModuleを再インポートする必要なく、PipeModuleにアクセスできます。

上記の「クロスモジュール」の回答に対する別の脚注:PipeModuleを作成したときに、forRoot静的メソッドを削除し、共有モジュールにそれなしでPipeModuleをインポートしました。私の基本的な理解は、forRootはシングルトンのようなシナリオに有用であり、必ずしもフィルターには適用されないということです。


1
これを追加していただきありがとうございます。それがSub-SharedModuleに追加されて初めて機能しました
jmcgrath207 '

ここでも同じですが、欠けていた部分はPipesModuleをSub-SharedModuleにインポートすることでした。
テンダーロイン

1

ここで別の答えを提案する:

パイプ用に別のモジュールを作成する必要はありませんが、間違いなく代替手段です。公式ドキュメントの脚注を確認してください:https : //angular.io/guide/pipes#custom-pipes

組み込みパイプを使用するのと同じ方法でカスタムパイプを使用します。
AppModuleの宣言配列にパイプを含める必要があります。パイプをクラスに注入することを選択した場合は、NgModuleのプロバイダー配列で提供する必要があります。

パイプを宣言配列に追加し、パイプを使用する場所にプロバイダー配列を追加するmoduleだけです。

declarations: [
...
CustomPipe,
...
],
providers: [
...
CustomPipe,
...
]

ただし、単一のパイプを2つのモジュールの一部にすることはできません。...上記のアプローチにより、さまざまなモジュールでより扱いやすくなります。
Himanshu Bansal

0

注:角度モジュールを使用していない場合のみ

何らかの理由でこれはドキュメントにありませんが、カスタムパイプをコンポーネントにインポートする必要がありました

import {UsersPipe} from './users-filter.pipe'

@Component({
    ...
    pipes:      [UsersPipe]
})

1
上記で投稿したPlunkerでは、パイプはappモジュールにインポートされ(コンポーネント自体と同じように)、そのモジュール内のすべてのコンポーネントでパイプを使用できるようになります。
ABabin 2016

実際、カスタムパイプを実際に使用するコンポーネントを見ていました。appモジュールでグローバルにインポートできることを知りませんでした。ありがとう
Sumama Waheed

users-filter.pipe?なぜ.pipe?
Nather Webber 2016

1
これは単なる命名規則です。ファイルの名前はusers-filter.pipe.tsです
Sumama Waheed

2
@SachinThampanは、angularがrc5にあったときだったからかもしれません。NgModuleのドキュメントをご覧ください
Sumama Waheed

-1
import { Component, Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'timePipe'
})
export class TimeValuePipe implements PipeTransform {

  transform(value: any, args?: any): any {
   var hoursMinutes = value.split(/[.:]/);
  var hours = parseInt(hoursMinutes[0], 10);
  var minutes = hoursMinutes[1] ? parseInt(hoursMinutes[1], 10) : 0;
  console.log('hours ', hours);
  console.log('minutes ', minutes/60);
  return (hours + minutes / 60).toFixed(2);
  }
}
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = 'Angular';
  order = [
    {
      "order_status": "Still at Shop",
      "order_id": "0:02"
    },
    {
      "order_status": "On the way",
      "order_id": "02:29"
    },
    {
      "order_status": "Delivered",
      "order_id": "16:14"
    },
     {
      "order_status": "Delivered",
      "order_id": "07:30"
    }
  ]
}

Invoke this module in App.Module.ts file.

-2

パイプが存在するのと同じディレクトリにパイプ用のモジュールを作成しました

import { NgModule } from '@angular/core';
///import pipe...
import { Base64ToImage, TruncateString} from './'  

   @NgModule({
        imports: [],
        declarations: [Base64ToImage, TruncateString],
        exports: [Base64ToImage, TruncateString]
    })

    export class SharedPipeModule { }   

次に、そのモジュールをapp.moduleにインポートします。

import {SharedPipeModule} from './pipe/shared.pipe.module'
 @NgModule({
     imports: [
    ...
    , PipeModule.forRoot()
    ....
  ],

ネストされたモジュールに同じものをインポートして使用できるようになりました

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.