找不到管道''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
您是否将其包括在组件的管道中?
哈里·宁

我只是意识到那是原因。自定义管道的角度示例为何从来没有这样做:angular.io/resources/live-examples/pipes/ts/plnkr.html
Sumama Waheed,

他们将其定义为全局管道。如果您在许多地方使用自定义管道并且不想在每个注解中都定义,则可以对自定义管道执行相同的操作。
哈里·宁

@SumamaWaheed我很确定它在文档中的某个时候存在,但是您是正确的,现在文档中没有提及/显示它。
米开朗基罗

Answers:


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中找不到管道的错误。*此外,我还使用了仅与使用的命名约定相关的打字稿“警告”,解决了这些问题后,有助于该自定义管道正确转换并最终被发现在模板中。
CNSKnight

这确实是对我有用的唯一解决方案!我尝试了整个共享模块,但是这种解决方案却很吸引人。谢谢@Karl!
lulu88

我们如何在组件测试中对此进行测试,
apoorva '17

2
谢谢!我的问题是我错过了“ exports:[myPipe]”,以为导出仅用于模块!
拉菲克·穆罕默德

55

您需要在模块声明中包含管道:

declarations: [ UsersPipe ],
providers: [UsersPipe]

5
请注意,我最初只是将管道包括在提供程序中。这需要同时包含在模块文件的声明和提供程序中。
格雷格A

我一直在努力,直到我听从你的建议。我浪费了大约4个小时才弄清楚。感谢您的建议。
user1501382 '17

5
为什么没有记录?文档状态为You must include your pipe in the declarations array of the AppModule.angular.io/guide/pipes。无论如何,您的回答也解决了我的问题。
Martijn

谢谢,尤瓦尔斯。我添加了一个细节:需要管道的模块声明。
Vinicios Torres'17

5
exports: [UsersPipe]如果该模块将由其他模块导入,请不要忘记也包括在内。
预制

18

对于Ionic,@ Karl提到您可能会遇到多个问题。对于离子型惰性加载页面而言,完美解决方案是:

  1. 使用以下文件创建管道目录:pipes.tspipes.module.ts

// pipe.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内容

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导入部分中

    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>


谢谢,这是离子的救星。因为“离子生成管道....”不会生成所需的所有步骤,例如创建pipes.module.ts。您的方法效果很好。注意,对于ionic v4,需要对导入路径进行一些小的更改。
royappa

1
我发现您不需要在app.module.ts中导入,因此可以省略该步骤。一定是因为“共享模块”无论如何都需要导入到其他模块中。如果app.module导入在全球范围内都可以,那就好了,但是我尝试了,但没有成功。
royappa

我仍然面临着这个问题:控制台错误文件:node_modules/@angular/core/fesm5/core.js:4002:0错误错误:未捕获(已承诺):NullInjectorError:StaticInjectorError(AppModule)[ToHtmlPipe-> DomSanitizer]:StaticInjectorError (平台:核心)[ToHtmlPipe-> DomSanitizer]:NullInjectorError:没有DomSanitizer的提供者!
mircobabini

12

我发现上面的“跨模块”答案对我的情况非常有帮助,但由于需要考虑的其他问题,我想对此进行扩展。如果您有子模块,那么在我的测试中它也看不到父模块中的管道。因此,您可能需要将管道放入自己的单独模块中。

这是我为解决子模块中不可见的管道而采取的步骤的摘要:

  1. 从(父)SharedModule中取出管道,然后放入PipeModule中
  2. 在SharedModule中,导入并导出PipeModule(对于依赖于SharedModule的应用程序的其他部分,以自动获得对PipeModule的访问权限)
  3. 对于Sub-SharedModule,请导入PipeModule,这样它就可以访问PipeModule,而不必重新导入SharedModule,这将造成循环依赖问题以及其他问题。

上述“跨模块”答案的另一个脚注:创建PipeModule时,删除了forRoot静态方法,并在共享模块中导入了不带静态方法的PipeModule。我的基本理解是forRoot对于单例之类的场景很有用,这些场景不一定适用于过滤器。


1
感谢您添加此内容。它仅对我有用,一旦将其添加到Sub-SharedModule
jmcgrath207 '17

是的,在这里,我缺少的部分是将PipesModule导入到Sub-SharedModule中。
里脊

1

在这里建议一个替代答案:

不需要为Pipe创建单独的模块,但绝对是一种选择。检查官方文档脚注:https : //angular.io/guide/pipes#custom-pipes

您使用自定义管道的方式与使用内置管道的方式相同。
您必须将管道包含在AppModule的声明数组中。如果选择将管道注入类,则必须在NgModule的providers数组中提供它。

您所要做的就是将管道添加到声明数组,并在要使用管道的位置添加providers数组module

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

但是单个管道不能成为2个模块的一部分。...上述方法使它在不同模块中更易于使用。
Himanshu Bansal

0

注意:仅当您不使用角度模块时

由于某种原因,这不在文档中,但我必须在组件中导入自定义管道

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

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

1
在上面发布的Plunker中,管道被导入到app模块中(与组件本身一样),这使得该管道可用于该模块中的所有组件。
ABabin '16

哦,好了,我实际上正在查看实际使用自定义管道的组件。我不知道它可以在app模块中全局导入。谢谢
Sumama Waheed

用户filter.pipe?为什么是.pipe?
Nather Webber

1
那只是一个命名约定,文件称为users-filter.pipe.ts
Sumama Waheed 16-10-14

2
@SachinThampan可能是因为这是我想在rc5中使用angular的时候..此后特别是使用NgModule进行了更改。请看文档的NgModule
Sumama瓦希德

-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()
    ....
  ],

现在可以通过将其导入嵌套模块中来使用它

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.