O tubo '' não foi encontrado tubo personalizado angular2

105

Não consigo consertar esse erro. Eu tenho uma barra de pesquisa e um ngFor. Estou tentando filtrar a matriz usando um tubo personalizado como este:

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);
  }
}

Uso:

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

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

Erro:

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)">

Versões angulares:

"@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"
Sumama Waheed
fonte
1
Você o incluiu nos Pipes do Componente?
Harry Ninh de
Acabei de perceber que esse era o motivo. Por que o exemplo angular para tubo personalizado nunca faz isso: angular.io/resources/live-examples/pipes/ts/plnkr.html
Sumama Waheed
Eles o definiram como um tubo global. Você pode fazer o mesmo com seu canal personalizado se usá-lo em muitos lugares e não quiser definir em cada anotação.
Harry Ninh de
@SumamaWaheed Tenho certeza de que estava lá em algum ponto nos documentos, mas você está correto, os documentos agora não mencionam / mostram isso.
Michelangelo

Respostas:

144

Certifique-se de não estar enfrentando um problema de "módulo cruzado"

Se o componente que está usando o pipe não pertencer ao módulo que declarou o componente do pipe "globalmente", então o pipe não foi encontrado e você receberá esta mensagem de erro.

No meu caso, declarei o tubo em um módulo separado e importei esse módulo de tubo em qualquer outro módulo com componentes que usam o tubo.

Eu declarei que o componente no qual você está usando o tubo é

o Módulo de Tubulação

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

Uso em outro módulo (por exemplo, app.module)

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

  @NgModule({
     imports: [
    ...
    , PipeModule.forRoot()
    ....
  ],
Karl
fonte
6
Essa solução foi a única que funcionou para mim. Acontece que os tubos precisam ter um módulo
AJ Zane
Eu também descobri que isso resolveu parcialmente o erro do cachimbo não encontrado no Ng 2.8. * Além disso, eu tinha "avisos" datilografados relacionados apenas às convenções de nomenclatura em uso, que ao resolvê-los, contribuíram para que esse cachimbo personalizado transpilasse corretamente e finalmente fosse encontrado no modelo.
CNSKnight 01 de
Esta é realmente a única solução que funcionou para mim! Tentei todo o módulo compartilhado, mas essa solução funcionou perfeitamente. Obrigado @Karl!
lulu88
como testamos isso em nosso teste de componente,
apoorva
2
Obrigado! Meu problema foi que perdi "exportações: [myPipe]" pensando que as exportações são apenas para módulos!
Rafique Mohammed
55

Você precisa incluir seu tubo na declaração do módulo:

declarations: [ UsersPipe ],
providers: [UsersPipe]
Yuvals
fonte
5
Apenas uma observação: originalmente, apenas incluí o pipe nos provedores. Isso precisa ser incluído em declarações e provedores no arquivo de módulo.
Greg A
Eu estava lutando até seguir sua sugestão. Eu perdi cerca de 4 horas apenas para descobrir isso. Obrigado pela sugestão.
user1501382
5
Por que isso não está documentado? A documentação informa You must include your pipe in the declarations array of the AppModule.: angular.io/guide/pipes . Enfim, sua resposta também resolve meu problema.
Martijn
Obrigado, Yuvals. Acrescento um detalhe: declaração do módulo onde você precisa do tubo.
Vinicios Torres
5
Não se esqueça de incluir também exports: [UsersPipe]se o módulo for importado por outros módulos.
Precástico de
18

No Ionic, você pode enfrentar vários problemas, como @Karl mencionou. A solução que funciona perfeitamente para páginas iônicas de carregamento lento é:

  1. Crie o diretório de pipes com os seguintes arquivos: pipes.ts e pipes.module.ts

// conteúdo de pipes.ts (pode ter vários tubos dentro, lembre-se de

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;
  }
}

// conteúdo de 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. Incluir PipesModule na seção de importações app.module e @NgModule

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

  2. Inclua PipesModule em cada um de seus .module.ts onde deseja usar tubos personalizados. Não se esqueça de adicioná-lo na seção de importações. // Exemplo. arquivo: pages / my-custom-page / my-custom-page.module.ts

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

  3. É isso aí. Agora você pode usar seu tubo personalizado em seu modelo. Ex.

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

Timothy
fonte
Este foi um salva-vidas para o iônico, obrigado. Porque "gerar tubo iônico ...." não gera todas as etapas necessárias, como a criação de pipes.module.ts. Sua abordagem funcionou perfeitamente. Observe, para iônico v4, algumas pequenas alterações são necessárias para os caminhos de importação.
royappa
1
Descobri que você não precisa das importações em app.module.ts, portanto, essa etapa pode ser omitida. Deve ser porque o "módulo compartilhado" está sendo importado para um outro módulo onde é necessário. Seria bom se a importação app.module funcionasse globalmente, mas eu tentei e não funcionou.
royappa
Ainda estou enfrentando isso: Arquivo CONSOLE ERROR: node_modules/@angular/core/fesm5/core.js: 4002: 0 ERROR Error: Uncaught (em promessa): NullInjectorError: StaticInjectorError (AppModule) [ToHtmlPipe -> DomSanitizer]: StatricInjectorE (Plataforma: core) [ToHtmlPipe -> DomSanitizer]: NullInjectorError: Nenhum provedor para DomSanitizer!
mircobabini 01 de
12

Achei a resposta "módulo cruzado" acima muito útil para minha situação, mas gostaria de expandir isso, pois há outra questão a considerar. Se você tiver um submódulo, ele também não poderá ver os tubos no módulo pai em meus testes. Por esse motivo também, você pode precisar colocar tubos em seu próprio módulo separado.

Aqui está um resumo das etapas que executei para resolver os canos que não eram visíveis no submódulo:

  1. Retire os tubos do (pai) SharedModule e coloque-os no PipeModule
  2. Em SharedModule, importe PipeModule e exporte (para outras partes do aplicativo dependentes de SharedModule para obter acesso automático ao PipeModule)
  3. Para Sub-SharedModule, importe PipeModule, para que ele possa obter acesso ao PipeModule, sem ter que reimportar SharedModule que criaria um problema de dependência circular, entre outros problemas.

Outra nota de rodapé para a resposta do "módulo cruzado" acima: quando criei o PipeModule, removi o método estático forRoot e importei o PipeModule sem isso no meu módulo compartilhado. Meu entendimento básico é que forRoot é útil para cenários como singletons, que não se aplicam necessariamente a filtros.

Sarora
fonte
1
Obrigado por adicionar isso. Só funcionou para mim depois de adicionado ao Sub-SharedModule
jmcgrath207
Sim mesmo aqui, a parte que estava faltando era importar PipesModule para o Sub-SharedModule.
filé mignon de
1

Sugerindo uma resposta alternativa aqui:

Não é necessário fazer um módulo separado para o Pipe , mas é definitivamente uma alternativa. Verifique a nota de rodapé da documentação oficial: https://angular.io/guide/pipes#custom-pipes

Você usa seu cano personalizado da mesma forma que usa canos embutidos.
Você deve incluir seu pipe na matriz de declarações do AppModule. Se você escolher injetar seu pipe em uma classe, deverá fornecê-lo na matriz de provedores de seu NgModule.

Tudo que você precisa fazer é adicionar seu pipe ao array de declarações e o array de fornecedoresmodule onde deseja usar o Pipe.

declarations: [
...
CustomPipe,
...
],
providers: [
...
CustomPipe,
...
]
Ykadaru
fonte
Mas um único tubo não pode fazer parte de 2 módulos ... A abordagem acima o torna mais acessível em diferentes módulos.
Himanshu Bansal
0

Nota : Somente se você não estiver usando módulos angulares

Por algum motivo, isso não está nos documentos, mas tive que importar o canal personalizado no componente

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

@Component({
    ...
    pipes:      [UsersPipe]
})
Sumama Waheed
fonte
1
No Plunker que você postou acima, os tubos são importados no módulo de app (exatamente como você faz com os próprios componentes), o que torna o tubo disponível para todos os componentes desse módulo.
ABabin de
Ok, na verdade, eu estava olhando para o componente que realmente usa o tubo personalizado. Eu não sabia que poderia ser importado globalmente no módulo de app. Obrigado
Sumama Waheed
users-filter.pipe? porque .pipe?
Nather Webber
1
Isso é apenas uma convenção de nomenclatura, o arquivo é chamado users-filter.pipe.ts
Sumama Waheed
2
@SachinThampan pode ser porque isso foi quando o angular estava no rc5 eu acho ... as coisas mudaram desde então, especialmente com o NgModule. Por favor, olhe os documentos para 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.
Chowdeswara Rao
fonte
-2

Eu criei um módulo para tubos no mesmo diretório onde meus tubos estão presentes

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

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

    export class SharedPipeModule { }   

Agora importe esse módulo em app.module:

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

Agora ele pode ser usado importando o mesmo no módulo aninhado

Amit Saini
fonte