Angular Pipe не работает на дочерних маршрутах

У меня очень простая труба в Angular 5

import { Pipe, Injectable } from '@angular/core';

@Pipe({
    name: "default"
})
@Injectable()
export class DefaultPipe {
    transform(value: string, fallback: string): string {
        let image = "";
        if (value) {
            image = value;
        } else {
            image = fallback;
        }
        return image;
    }
}

и я использую его очень просто для демонстрации

<div>
    {{ 'somthing' | default }}
</div> 

Я также добавил в раздел поставщика в app.module.ts

@NgModule({
    declarations: [
        AppComponent,
        DefaultPipe // <-- Here
    ],
    imports: [
        ....
    ],
    providers: [
        ....
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

когда вы используете его в обычном компоненте, таком как

app.component.html

он работает нормально, но если вы используете его в компоненте, который используется в дочернем маршруте, он дает следующую ошибку:

compiler.js:486 Uncaught Error: Template parse errors: The pipe 'default' could not be found ("

{{[ERROR ->] 'somthing' | default }} "): ng:///AppRoutingModule/LoginComponent.html@75:6 at syntaxError (compiler.js:486) at TemplateParser.webpackJsonp../node_modules/@angular/compiler/esm5/compiler.js.TemplateParser.parse (compiler.js:24674) at JitCompiler.webpackJsonp../node_modules/@angular/compiler/esm5/compiler.js.JitCompiler._parseTemplate (compiler.js:34629) at JitCompiler.webpackJsonp../node_modules/@angular/compiler/esm5/compiler.js.JitCompiler._compileTemplate (compiler.js:34604) at compiler.js:34505 at Set.forEach () at JitCompiler.webpackJsonp../node_modules/@angular/compiler/esm5/compiler.js.JitCompiler._compileComponents (compiler.js:34505) at compiler.js:34375 at Object.then (compiler.js:475) at JitCompiler.webpackJsonp../node_modules/@angular/compiler/esm5/compiler.js.JitCompiler._compileModuleAndComponents (compiler.js:34374)

Решать:

Я добавил этот модуль как share.module.ts

import { NgModule } from '@angular/core';
import { DefaultPipe } from './core/pipes/default.pipe';

@NgModule({
    declarations: [DefaultPipe],
    exports: [DefaultPipe]
})
export class SharedModule { }

и использовал его в двух местах, одно в app.module.ts:

@NgModule({
declarations: [
    AppComponent,
],
imports: [
    ...
    // other modules
    ...
    SharedModule
],
providers: [
    ....
],
bootstrap: [AppComponent]

}) класс экспорта AppModule {}

и один в route.module.ts

@NgModule({
    declarations: [
        ....
    ],
    imports: [
        ....
        SharedModule
    ],
    exports: [
        RouterModule,
    ]
})

export class AppRoutingModule { }

не могли бы вы добавить модуль, в котором вы объявляете LoginComponent?

Jota.Toledo 01.06.2018 11:06

Почему голосование против? вы прикладываете все усилия, чтобы решить проблему со многими объяснениями, и вот вы идете, вы получаете голосование, ТАК БОЛЬШОЕ СПАСИБО !!!

Ehsan Zargar Ershadi 18.06.2018 11:19
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
2
2
1 947
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вам не нужно использовать декоратор Injectable для канала, поэтому вы можете удалить его.

Кроме того, как уже предлагалось в других ответах, я бы порекомендовал вам явно реализовать интерфейс PipeTransform, чтобы он соответствовал API канала.

compiler.js:486 Uncaught Error: Template parse errors: The pipe 'default' could not be found ("

{{[ERROR ->] 'somthing' | default }} "): ng:///AppRoutingModule/LoginComponent.html@75:6 at syntaxError (compiler.js:486)

в основном говорит о том, что ваш канал не был ни объявлен, ни импортирован в модуль, в котором объявлен LoginComponent.

Самым простым и чистым решением было бы объявить / экспортировать канал внутри нового класса NgModule, который затем можно было бы импортировать в каждый модуль, объявляющий компонент, использующий канал. Например:

@NgModule({
  declarations: [DefaultPipe],
  exports: [DefaultPipe]
})
export class DefaultPipeModule{}

@NgModule({
  imports: [DefaultPipeModule],
  declarations: [LoginComponent]
})
export class FooModule {}

@NgModule({
  imports: [DefaultPipeModule],
  declarations: [FooComponent] // fooComponent also uses the default pipe, so we need to import its module
})
export class SomeOtherModule{}

Я не знаю, почему они проголосовали против, но ваше предложение действительно было правильным и помогло решить мою проблему. Я добавил модуль общего доступа и использовал его в своем модуле маршрута и модуле приложения, и он сработал. Спасибо

Ehsan Zargar Ershadi 01.06.2018 11:41

@EhsanZargarErshadi, не могли бы вы добавить информацию, которую я запросил, в комментарии к вашему вопросу? просто чтобы убедиться, что ваш вопрос может помочь другим

Jota.Toledo 01.06.2018 11:45

Ссылка: здесь

Пользовательская труба:

Прежде всего, нет @Injectable (), поскольку это не служба, которую вы определяете в конструкторе. Затем вам нужно импортировать PipeTransform из '@angular/core' и реализовать его.

Пример:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
    name: "default"
})

export class DefaultPipe implements PipeTransform {
    transform(value: string, fallback: string): string {
        let image = "";
        if (value) {
            image = value;
        } else {
            image = fallback;
        }
        return image;
    }
}

Лучшая практика для создания вспомогательных компонентов, каналов или директив - создать SharedModule и поместить его внутрь.

Компоненты, директивы и конвейеры не работают как службы. Сервис, который вы можете внедрить в массив сервисов AppModule, и он будет работать и для детей.

Канал, директиву или компонент, вы должны объявить их в NgModule, а затем импортировать их туда, где они вам нужны, потому что они могут ТОЛЬКО относится к 1 модулю. (Но этот модуль можно импортировать сколько угодно раз!)

Поэтому лучшее, что вы можете сделать, - это создать SharedModule со следующим:

@NgModule({
  imports: [ ... ],
  declarations: [ DefaultPipe ],
  exports: [ DefaultPipe ]
})
export class SharedModule { }

А затем в AppModule вы импортируете SharedModule следующим образом:

imports: [ SharedModule ]

А теперь, если вы хотите использовать его в своем компоненте LoginComponent или в любой другой части вашего приложения, вы импортируете свой SharedModule в модуль для этого компонента.

Другие вопросы по теме