Nie można znaleźć rury niestandardowej „angular2”

105

Nie mogę naprawić tego błędu. Mam pasek wyszukiwania i plik ngFor. Próbuję przefiltrować tablicę za pomocą niestandardowego potoku, takiego jak ten:

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

Stosowanie:

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

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

Błąd:

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

Wersje kątowe:

"@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
źródło
1
Czy umieściłeś to w rurach komponentu?
Harry Ninh,
Właśnie zdałem sobie sprawę, że to był powód. Dlaczego kątowy przykład niestandardowej rury nigdy tego nie robi: angular.io/resources/live-examples/pipes/ts/plnkr.html
Sumama Waheed
Zdefiniowali to jako globalną rurę. Możesz zrobić to samo z niestandardową potoką, jeśli używasz jej w wielu miejscach i nie chcesz definiować jej w każdej adnotacji.
Harry Ninh,
@SumamaWaheed Jestem prawie pewien, że to było w pewnym momencie w dokumentach, ale masz rację, dokumenty teraz nie wspominają o tym / nie pokazują tego.
Michelangelo

Odpowiedzi:

144

Upewnij się, że nie masz problemu z „modułami krzyżowymi”

Jeśli komponent używający potoku nie należy do modułu, który zadeklarował komponent potoku „globalnie”, potok nie zostanie znaleziony i pojawi się ten komunikat o błędzie.

W moim przypadku zadeklarowałem rurę w oddzielnym module i zaimportowałem ten moduł rurowy do dowolnego innego modułu zawierającego komponenty wykorzystujące rurę.

Zadeklarowałem, że komponent, w którym używasz rury, jest

moduł rurowy

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

Wykorzystanie w innym module (np. App.module)

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

  @NgModule({
     imports: [
    ...
    , PipeModule.forRoot()
    ....
  ],
Karl
źródło
6
To rozwiązanie było jedynym, które działało dla mnie. Okazuje się, że rury muszą mieć moduł
AJ Zane
Ja również znalazłem to, aby częściowo rozwiązać mój błąd nie znaleziono potoku w Ng 2.8. * Dodatkowo, miałem "ostrzeżenia" maszynopisu związane tylko z używanymi konwencjami nazewnictwa, które po ich rozwiązaniu przyczyniły się do poprawnej transpozycji niestandardowego potoku i ostatecznego znalezienia w szablonie.
CNSKnight
To naprawdę jedyne rozwiązanie, które zadziałało! Wypróbowałem cały wspólny moduł, ale to rozwiązanie działało jak urok. Dziękuję @Karl!
lulu88
jak to sprawdzić w naszym teście komponentów,
apoorva,
2
Dzięki! Mój problem polegał na tym, że przegapiłem „export: [myPipe]” myśląc, że eksport dotyczy tylko modułów!
Rafique Mohammed
55

Musisz dołączyć potok do deklaracji modułu:

declarations: [ UsersPipe ],
providers: [UsersPipe]
Yuvals
źródło
5
Uwaga, pierwotnie włączyłem rurę do dostawców. Należy to uwzględnić zarówno w deklaracjach, jak i dostawcach w pliku modułu.
Greg A,
Walczyłem, dopóki nie zastosowałem się do twojej sugestii. zmarnowałem około 4 godzin, żeby to rozgryźć. Dziękuję za sugestię.
user1501382
5
Dlaczego nie jest to udokumentowane? Dokumentacja stwierdza You must include your pipe in the declarations array of the AppModule.: angular.io/guide/pipes . W każdym razie twoja odpowiedź również rozwiązuje mój problem.
Martijn
Dzięki, Yuvals. Dodam szczegół: deklaracja modułu gdzie potrzebujesz potoku.
Vinicios Torres
5
Nie zapomnij również uwzględnić, exports: [UsersPipe]czy moduł ma być importowany przez inne moduły.
Precyzyjny
18

W przypadku Ionic możesz napotkać wiele problemów, o których wspomniał @Karl. Rozwiązaniem, które działa bezbłędnie w przypadku jonowych, leniwych ładowanych stron, jest:

  1. Utwórz katalog potoków z następującymi plikami: pipe.ts i pipes.module.ts

// pipe.ts content (może zawierać wiele potoków w środku, pamiętaj tylko o tym

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

// pipe.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. Dołącz PipesModule do sekcji importu app.module i @NgModule

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

  2. Dołącz PipesModule do każdego pliku .module.ts, w którym chcesz używać niestandardowych potoków. Nie zapomnij dodać go do sekcji importu. // Przykład. file: pages / my-custom-page / my-custom-page.module.ts

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

  3. Otóż ​​to. Teraz możesz użyć niestandardowej rury w swoim szablonie. Dawny.

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

Tymotka
źródło
To był ratunek dla jonów, dzięki. Ponieważ "ionic generowanie potoku ...." nie generuje wszystkich potrzebnych kroków, takich jak tworzenie pipe.module.ts. Twoje podejście zadziałało doskonale. Uwaga, w przypadku ionic v4 potrzebne są niewielkie zmiany w ścieżkach importu.
royappa
1
Okazało się, że nie potrzebujesz importu w app.module.ts, więc ten krok można pominąć. Musi tak być, ponieważ „moduł współdzielony” i tak jest importowany do każdego innego modułu tam, gdzie jest potrzebny. Byłoby miło, gdyby importowanie modułu app.module działało globalnie, ale próbowałem i nie działa.
royappa
Nadal mam do czynienia z tym: plik BŁĘDU KONSOLI: node_modules/@angular/core/fesm5/core.js: 4002: 0 BŁĄD Błąd: Uncaught (w obietnicy): NullInjectorError: StaticInjectorError (AppModule) [ToHtmlPipe -> DomSanitizer]: Static (Platforma: core) [ToHtmlPipe -> DomSanitizer]: NullInjectorError: Brak dostawcy dla DomSanitizer!
mircobabini
12

Uważam, że powyższa odpowiedź „modułu krzyżowego” jest bardzo pomocna w mojej sytuacji, ale chciałbym ją rozwinąć, ponieważ jest jeszcze jedna kwestia do rozważenia. Jeśli masz moduł podrzędny, nie widzi on również rur w module nadrzędnym podczas moich testów. Z tego też powodu może być konieczne umieszczenie rur w tym oddzielnym module.

Oto podsumowanie kroków, które podjąłem, aby rozwiązać problem niewidocznych potoków w module podrzędnym:

  1. Wyjmij rury z (nadrzędnego) SharedModule i włóż do PipeModule
  2. W SharedModule importuj PipeModule i eksportuj (dla innych części aplikacji zależnych od SharedModule, aby automatycznie uzyskać dostęp do PipeModule)
  3. W przypadku Sub-SharedModule zaimportuj PipeModule, aby uzyskać dostęp do PipeModule bez konieczności ponownego importowania SharedModule, co spowodowałoby między innymi problem z cyklicznymi zależnościami.

Kolejny przypis do powyższej odpowiedzi „cross module”: kiedy tworzyłem PipeModule, usunąłem statyczną metodę forRoot i zaimportowałem PipeModule bez tego w moim współdzielonym module. Moje podstawowe rozumienie jest takie, że forRoot jest przydatny w scenariuszach takich jak singletony, które niekoniecznie mają zastosowanie do filtrów.

sarora
źródło
1
Dziękuję za dodanie tego. U mnie zadziałało tylko wtedy, gdy został dodany do Sub-SharedModule
jmcgrath207
Tak samo tutaj, brakowało mi importowanie PipesModule do Sub-SharedModule.
polędwica
1

Sugerowanie alternatywnej odpowiedzi tutaj:

Wykonanie oddzielnego modułu dla Pipe nie jest wymagane , ale jest zdecydowanie alternatywą. Sprawdź oficjalny przypis do dokumentów: https://angular.io/guide/pipes#custom-pipes

Używasz niestandardowej rury w taki sam sposób, jak używasz rur wbudowanych.
Musisz dołączyć swój potok do tablicy deklaracji AppModule. Jeśli zdecydujesz się wstrzyknąć potok do klasy, musisz podać go w tablicy dostawców swojego NgModule.

Wszystko, co musisz zrobić, to dodać potok do tablicy deklaracji , a tablicę dostawców w miejscu, w modulektórym chcesz użyć potoku .

declarations: [
...
CustomPipe,
...
],
providers: [
...
CustomPipe,
...
]
ykadaru
źródło
Ale pojedyncza rura nie może być częścią 2 modułów ... Powyższe podejście czyni ją bardziej dostępną w różnych modułach.
Himanshu Bansal
0

Uwaga: tylko jeśli nie używasz modułów kątowych

Z jakiegoś powodu nie ma tego w dokumentacji, ale musiałem zaimportować niestandardową rurę w komponencie

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

@Component({
    ...
    pipes:      [UsersPipe]
})
Sumama Waheed
źródło
1
W opublikowanym powyżej Plunkerze rury są importowane do modułu aplikacji (dokładnie tak, jak robisz to z samymi komponentami), co sprawia, że ​​rura jest dostępna dla wszystkich komponentów w tym module.
ABabin
Aha, tak naprawdę patrzyłem na komponent, który faktycznie używa niestandardowej rury. Nie wiedziałem, że można go zaimportować globalnie w module aplikacji. Dzięki
Sumama Waheed
users-filter.pipe? dlaczego .pipe?
Nather Webber,
1
To tylko konwencja nazewnictwa, plik nazywa się users-filter.pipe.ts
Sumama Waheed
2
@SachinThampan może być, ponieważ to było, gdy angular był w rc5, myślę, że od tego czasu wszystko się zmieniło, szczególnie w NgModule. Proszę spojrzeć na dokumentację 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
źródło
-2

Utworzyłem moduł dla rur w tym samym katalogu, w którym znajdują się moje potoki

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

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

    export class SharedPipeModule { }   

Teraz zaimportuj ten moduł do app.module:

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

Teraz można go użyć, importując to samo w zagnieżdżonym module

Amit Saini
źródło