Трубу "" не вдалося знайти під кутом2 спеціальної труби


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 Я майже впевнений, що він був у якийсь момент у документах, але ви правильні, що документи тепер не згадують / не показують.
Мікеланджело

Відповіді:


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

2
Дякую! Моєю проблемою було те, що я пропустив "експорт: [myPipe]", думаючи, що експорт призначений лише для модулів!
Рафік Мухаммед

55

Вам потрібно включити свою трубу в декларацію модуля:

declarations: [ UsersPipe ],
providers: [UsersPipe]

5
Лише зауваження, спочатку я просто включив трубу в провайдери. Це потрібно включити як у декларації, так і у провайдери у файл модуля.
Грег А

Я боровся, поки я не дотримувався вашої пропозиції. Я витратив близько 4 годин, щоб просто зрозуміти це. Дякую за пропозицію.
user1501382

5
Чому це не підтверджено документально? У документації зазначено You must include your pipe in the declarations array of the AppModule.: angular.io/guide/pipes . У будь-якому випадку, ваша відповідь також вирішує мою проблему.
Мартійн

Спасибі, Ювальс. Додаю деталь: оголошення модуля, де вам потрібна труба.
Vinicios Torres

5
Не забудьте також включити, exports: [UsersPipe]якщо модуль буде імпортований іншими модулями.
Передбачливий

18

Для Ionic ви можете зіткнутися з декількома проблемами, як згадував @Karl. Рішення, яке бездоганно працює для іонних ледачих завантажених сторінок:

  1. Створіть каталог труб із такими файлами: pipe.ts та pipe.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;
  }
}

// content.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. Включіть PipesModule у свій .module.ts, де ви хочете використовувати спеціальні труби. Не забудьте додати його до розділу про імпорт. // Приклад. файл: сторінки / моя-користувальницька сторінка / мій-користувальницький-сторінку.module.ts

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

  3. Це воно. Тепер ви можете використовувати свою власну трубу у своєму шаблоні. Вих.

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


Це було рятувальником іонних, дякую. Оскільки "іонна генерація труби ...." не генерує всіх необхідних кроків, як, наприклад, створення pipe.module.ts. Ваш підхід спрацював ідеально. Зауважте, що для ionic v4 потрібні деякі невеликі зміни в шляхах імпорту.
royappa

1
Я виявив, що імпорт у app.module.ts вам не потрібний, тому цей крок можна опустити. Це повинно бути тому, що він "загальний модуль" все одно імпортується в один інший модуль там, де це потрібно. Було б добре, якби імпорт app.module працював у всьому світі, але я спробував, але це не так.
royappa

Я все ще стикаюся з цим: файл CONSOLE ERROR: node_modules/@angular/core/fesm5/core.js: 4002: 0 Помилка помилки: Uncaught (в обіцянні): NullInjectorError: StaticInjectorError (AppModule) [ToHtmlPipe -> DomSanitizer]: StaticInjector (Платформа: core) [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

Так-же тут, частина, яку мені бракувало, імпортувала PipesModule в Sub-SharedModule.
виступ

1

Запропонувати альтернативу відповідь:

Створення окремого модуля для Труби не потрібно , але, безумовно, альтернатива. Перегляньте офіційну виноску щодо документів: https://angular.io/guide/pipes#custom-pipes

Ви використовуєте власну трубу так само, як і вбудовані труби.
Ви повинні включити свою трубу в масив декларацій AppModule. Якщо ви вирішили ввести свою трубу в клас, ви повинні надати її в масиві постачальників вашого NgModule.

Все, що вам потрібно зробити, - це додати свою трубу до масиву декларацій , а постачальники масиву - moduleтам, де ви хочете використовувати Pipe.

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

Але одна труба не може бути частиною 2-х модулів .... Наведений вище підхід робить її більш доступною в різних модулях.
Himanshu Bansal

0

Примітка : Тільки якщо ви не використовуєте кутові модулі

Чомусь цього немає в документах, але мені довелося імпортувати користувальницьку трубку в компонент

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

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

1
У Plunker, який ви розмістили вище, труби імпортуються в модуль програми (точно так само, як і з самими компонентами), що робить цю трубку доступною для всіх компонентів цього модуля.
ABabin

Ой добре, я насправді дивився на компонент, який фактично використовує власну трубу. Я не знав, що це може бути імпортовано глобально в модулі додатків. Спасибі
Сумама Уахід

користувачі-filter.pipe? чому .pipe?
Nather Webber

1
Це лише умовність іменування, файл називається users-filter.pipe.ts
Sumama Waheed

2
@SachinThampan може бути, тому що це було, коли кутовий був у rc5, я думаю, що з того часу змінилися спеціально з NgModule. Ознайомтесь з документами для 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()
    ....
  ],

Тепер його можна використовувати, імпортуючи те саме в вкладений модуль

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.