Das Rohr '' konnte nicht gefunden werden. Angular2 custom pipe


105

Ich kann diesen Fehler scheinbar nicht beheben. Ich habe eine Suchleiste und ein ngFor. Ich versuche, das Array mit einer benutzerdefinierten Pipe wie folgt zu filtern:

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

Verwendung:

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

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

Error:

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

Winkelversionen:

"@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
Haben Sie es in die Pipes der Komponente aufgenommen?
Harry Ninh

Mir wurde gerade klar, dass das der Grund war. Wie kommt es, dass das Winkelbeispiel für benutzerdefinierte Rohre dies niemals tut: angle.io/resources/live-examples/pipes/ts/plnkr.html
Sumama Waheed

Sie definierten es als globale Pipe. Sie können dasselbe mit Ihrer benutzerdefinierten Pipe tun, wenn Sie sie an vielen Stellen verwenden und nicht in jeder einzelnen Anmerkung definieren möchten.
Harry Ninh

@SumamaWaheed Ich bin mir ziemlich sicher, dass es irgendwann in den Dokumenten vorhanden war, aber Sie haben Recht, die Dokumente erwähnen / zeigen es jetzt nicht.
Michelangelo

Antworten:


143

Stellen Sie sicher, dass Sie nicht mit einem "Cross-Modul" -Problem konfrontiert sind

Wenn die Komponente, die die Pipe verwendet, nicht zu dem Modul gehört, das die Pipe-Komponente als "global" deklariert hat, wird die Pipe nicht gefunden und Sie erhalten diese Fehlermeldung.

In meinem Fall habe ich die Pipe in einem separaten Modul deklariert und dieses Pipe-Modul in ein anderes Modul importiert, dessen Komponenten die Pipe verwenden.

Ich habe a deklariert, dass die Komponente, in der Sie die Pipe verwenden, ist

das Rohrmodul

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

Verwendung in einem anderen Modul (zB app.module)

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

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

6
Diese Lösung war die einzige, die für mich funktioniert hat. Es stellt sich heraus, dass Rohre ein Modul benötigen
AJ Zane

Auch ich fand dies, um meinen nicht gefundenen Pipe-Fehler in Ng 2.8 teilweise zu beheben. * Zusätzlich hatte ich maschinengeschriebene "Warnungen", die sich nur auf die verwendeten Namenskonventionen bezogen, die nach dem Lösen dieser Fehler dazu beitrugen, dass diese benutzerdefinierte Pipe ordnungsgemäß transpiliert und letztendlich gefunden wurde in der Vorlage.
CNSKnight

Dies ist wirklich die einzige Lösung, die für mich funktioniert hat! Ich habe das ganze gemeinsame Modul ausprobiert, aber diese Lösung hat wie ein Zauber funktioniert. Danke @Karl!
lulu88

Wie testen wir dies in unserem Komponententest
?

2
Vielen Dank! Mein Problem war, dass ich "Exporte: [myPipe]" verpasst habe und dachte, dass Exporte nur für Module sind!
Rafique Mohammed

55

Sie müssen Ihre Pipe in die Moduldeklaration aufnehmen:

declarations: [ UsersPipe ],
providers: [UsersPipe]

5
Nur eine Anmerkung, ich habe ursprünglich nur die Pipe in die Anbieter aufgenommen. Dies muss sowohl in Deklarationen als auch in Anbietern in der Moduldatei enthalten sein.
Greg A

Ich hatte Probleme, bis ich Ihrem Vorschlag folgte. Ich habe ungefähr 4 Stunden verschwendet, um es herauszufinden. Vielen Dank für den Vorschlag.
user1501382

5
Warum ist das nicht dokumentiert? In der Dokumentation heißt es You must include your pipe in the declarations array of the AppModule.: angle.io/guide/pipes . Wie auch immer, Ihre Antwort behebt auch mein Problem.
Martijn

Danke, Yuvals. Ich füge ein Detail hinzu: Deklaration des Moduls, in dem Sie die Pipe benötigen.
Vinicios Torres

5
Vergessen Sie nicht, auch anzugeben, exports: [UsersPipe]ob das Modul von anderen Modulen importiert werden soll.
Precastic

18

Für Ionic können mehrere Probleme auftreten, wie bei @Karl erwähnt. Die Lösung, die für ionisch träge geladene Seiten einwandfrei funktioniert, ist:

  1. Erstellen Sie ein Pipes-Verzeichnis mit folgenden Dateien: pipes.ts und pipes.module.ts

// pipes.ts Inhalt (es kann mehrere Pipes enthalten, denken Sie daran

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 Inhalt

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. Fügen Sie PipesModule in den Importabschnitt app.module und @NgModule ein

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

  2. Fügen Sie PipesModule in jede Ihrer .module.ts ein, in der Sie benutzerdefinierte Pipes verwenden möchten. Vergessen Sie nicht, es in den Importbereich aufzunehmen. // Beispiel. Datei: pages / my-custom-page / my-custom-page.module.ts

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

  3. Das ist es. Jetzt können Sie Ihre benutzerdefinierte Pipe in Ihrer Vorlage verwenden. Ex.

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


Dies war ein Lebensretter für ionische, danke. Weil "ionic generate pipe ...." nicht alle erforderlichen Schritte generiert, wie z. B. das Erstellen der pipes.module.ts. Ihr Ansatz hat perfekt funktioniert. Beachten Sie, dass für ionic v4 einige kleine Änderungen an den Importpfaden erforderlich sind.
Royappa

1
Ich habe festgestellt, dass Sie die Importe in app.module.ts nicht benötigen, sodass dieser Schritt weggelassen werden kann. Dies muss daran liegen, dass das "gemeinsam genutzte Modul" ohnehin in das andere Modul importiert wird, in dem es benötigt wird. Es wäre schön, wenn der Import von app.module global funktionieren würde, aber ich habe es versucht und es nicht.
Royappa

Ich stehe immer noch vor folgendem Problem: CONSOLE ERROR-Datei: node_modules/@angular/core/fesm5/core.js: 4002: 0 ERROR-Fehler: Nicht erfasst (im Versprechen): NullInjectorError: StaticInjectorError (AppModule) [ToHtmlPipe -> DomSanitizer]: StaticInjectorr (Plattform: Kern) [ToHtmlPipe -> DomSanitizer]: NullInjectorError: Kein Anbieter für DomSanitizer!
mircobabini

12

Ich fand die obige Antwort "Cross Module" sehr hilfreich für meine Situation, möchte sie aber erweitern, da noch eine weitere Falte zu berücksichtigen ist. Wenn Sie ein Submodul haben, kann es in meinen Tests auch die Pipes im übergeordneten Modul nicht sehen. Aus diesem Grund müssen Sie möglicherweise auch Rohre in ein separates Modul einbauen.

Hier ist eine Zusammenfassung der Schritte, die ich unternommen habe, um Pipes zu beheben, die im Submodul nicht sichtbar sind:

  1. Nehmen Sie die Rohre aus dem (übergeordneten) SharedModule und legen Sie sie in das PipeModule
  2. Importieren Sie in SharedModule PipeModule und exportieren Sie es (für andere Teile der App, die von SharedModule abhängig sind, um automatisch Zugriff auf PipeModule zu erhalten).
  3. Importieren Sie für Sub-SharedModule PipeModule, damit es auf PipeModule zugreifen kann, ohne SharedModule erneut importieren zu müssen, was unter anderem zu einem zirkulären Abhängigkeitsproblem führen würde.

Eine weitere Fußnote zur obigen "modulübergreifenden" Antwort: Als ich das PipeModule erstellte, entfernte ich die statische forRoot-Methode und importierte PipeModule ohne diese in mein freigegebenes Modul. Mein grundlegendes Verständnis ist, dass forRoot für Szenarien wie Singletons nützlich ist, die nicht unbedingt für Filter gelten.


1
Vielen Dank, dass Sie dies hinzugefügt haben. Es hat nur für mich funktioniert, als es zu Sub-SharedModule hinzugefügt wurde
sonance207

Ja, der Teil, den ich vermisst habe, war das Importieren von PipesModule in das Sub-SharedModule.
Filet

1

Hier eine alternative Antwort vorschlagen:

Das Erstellen eines separaten Moduls für das Rohr ist nicht erforderlich , aber definitiv eine Alternative. Überprüfen Sie die Fußnote der offiziellen Dokumente: https://angular.io/guide/pipes#custom-pipes

Sie verwenden Ihr benutzerdefiniertes Rohr genauso wie eingebaute Rohre.
Sie müssen Ihre Pipe in das Deklarationsarray des AppModule aufnehmen. Wenn Sie Ihre Pipe in eine Klasse einfügen möchten, müssen Sie sie im Provider-Array Ihres NgModule angeben.

Alles, was Sie tun müssen, ist, Ihre Pipe zum Deklarationsarray und das Provider- Array an der Stelle hinzuzufügen, an der moduleSie die Pipe verwenden möchten.

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

Ein einzelnes Rohr kann jedoch nicht Teil von zwei Modulen sein. Der obige Ansatz macht es in verschiedenen Modulen zugänglicher.
Himanshu Bansal

0

Hinweis : Nur wenn Sie keine Winkelmodule verwenden

Aus irgendeinem Grund ist dies nicht in den Dokumenten enthalten, aber ich musste die benutzerdefinierte Pipe in die Komponente importieren

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

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

1
In dem oben veröffentlichten Plunker werden die Pipes in das App-Modul importiert (genau wie bei den Komponenten selbst), wodurch das Pip für alle Komponenten in diesem Modul verfügbar wird.
ABabin

Oh ok, ich habe mir tatsächlich die Komponente angesehen, die tatsächlich das benutzerdefinierte Rohr verwendet. Ich wusste nicht, dass es global in das App-Modul importiert werden kann. Vielen Dank
Sumama Waheed

users-filter.pipe? warum .pipe?
Nather Webber

1
Das ist nur eine Namenskonvention, die Datei heißt users-filter.pipe.ts
Sumama Waheed

2
@SachinThampan könnte sein, weil dies war, als Winkel in RC5 war, denke ich ... Dinge haben sich seitdem speziell mit NgModule geändert. Bitte schauen Sie sich die Dokumente für 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

Ich habe ein Modul für Pipes in demselben Verzeichnis erstellt, in dem meine Pipes vorhanden sind

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

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

    export class SharedPipeModule { }   

Importieren Sie nun dieses Modul in app.module:

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

Jetzt kann es verwendet werden, indem dasselbe in das verschachtelte Modul importiert wird

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.