Angular 2 — повторное использование канала в нескольких модулях — ошибка не найдена или дублируется определение

Я работаю над финальным релизом angular 2.

Я объявил два модуля: основное приложение и один для страницы настроек.

Основной модуль объявляет глобальные каналы. Этот модуль также включает модуль настроек.

app.module.ts

@NgModule({
    imports: [BrowserModule, HttpModule, routing, FormsModule, SettingsModule],
    declarations: [AppComponent, JsonStringifyPipe],
    bootstrap: [AppComponent]
})
export class AppModule { }

settings.module.ts

@NgModule({
    imports: [CommonModule, HttpModule, FormsModule, routing],
    declarations: [SettingsComponent],
    exports: [SettingsComponent],
    providers: []
})
export class SettingsModule { }

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

zone.min.js?cb=bdf3d3f:1 Unhandled Promise rejection: Template parse errors:
The pipe 'jsonStringify' could not be found ("         <td>{{user.name}}</td>
                    <td>{{user.email}}</td>
                    <td>[ERROR ->]{{user | jsonStringify}}</td>
                    <td>{{ user.registered }}</td>
                </tr"): ManageSettingsComponent@44:24 ; Zone: <root> ; Task: Promise.then ; Value: Error: Template parse 

Если я включу канал в модуль настроек, он жалуется на то, что два модуля имеют один и тот же канал.

zone.min.js?cb=bdf3d3f:1 Error: Error: Type JsonStringifyPipe is part of the declarations of 2 modules: SettingsModule and AppModule! Please consider moving JsonStringifyPipe to a higher module that imports SettingsModule and AppModule. You can also create a new NgModule that exports and includes JsonStringifyPipe then import that NgModule in SettingsModule and AppModule.

json-stringify.pipe.ts

@Pipe({name: 'jsonStringify'})
export class JsonStringifyPipe implements PipeTransform {
    transform(object) {
        // Return object as a string
        return JSON.stringify(object);
    }
}

Любая идея об этом?


person kitimenpolku    schedule 13.10.2016    source источник


Ответы (1)


Если вы хотите использовать канал в другом модуле, добавьте модуль, в котором объявлен канал, в imports: [...] модуля, в котором вы хотите повторно использовать канал, вместо того, чтобы добавлять его в declarations: [] нескольких модулей.

Например:

@NgModule({
    imports: [],
    declarations: [JsonStringifyPipe],
    exports: [JsonStringifyPipe]
})
export class JsonStringifyModule { }
@NgModule({
    imports: [
      BrowserModule, HttpModule, routing, FormsModule, SettingsModule,
      JsonStringifyModule],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
@NgModule({
    imports: [
       CommonModule, HttpModule, FormsModule, routing, 
       JsonStringifyModule],
    declarations: [SettingsComponent],
    exports: [SettingsComponent],
    providers: []
})
export class SettingsModule { }
person Günter Zöchbauer    schedule 13.10.2016
comment
Спасибо за ответ... Зачем мне создавать модуль для пайпов? Почему определения канала в глобальном модуле недостаточно, чтобы сделать канал доступным для других модулей? - person kitimenpolku; 13.10.2016
comment
Почему хороший вопрос. Потому что Angular2 разработан таким образом. Думаю, это мало поможет ;-). Концепция NgModule была введена для того, чтобы заставить ленивую загрузку работать с компиляцией шаблонов в автономном режиме, и я думаю, у них были веские причины для ее разработки таким образом. Angular просто нужно знать, где используются компоненты, директивы, каналы и сервисы, чтобы иметь возможность создавать небольшой и эффективный код, который работает с отложенной загрузкой и автономной компиляцией. - person Günter Zöchbauer; 13.10.2016
comment
Вам не нужно создавать модуль для каждого канала. В такой модуль можно поместить сколько угодно повторно используемых компонентов, директив, пайпов и сервисов. Но вам нужно импортировать его везде, где используется одна из этих частей. - person Günter Zöchbauer; 13.10.2016
comment
Я думаю, что просто перепутал то, что можно делать в компонентах и ​​модулях. Кажется, что у компонентов есть иерархия — сервисы, зарегистрированные как поставщики для компонента, могут наследоваться другими компонентами. К модулям это не относится. В моем случае app.module и settings.module — независимые модули. App.module знает только экспорт из settings.module. Settings.module не знает о App.module. Надеюсь, я правильно понимаю. - person kitimenpolku; 13.10.2016
comment
Вроде понял ;-) - person Günter Zöchbauer; 13.10.2016
comment
@GünterZöchbauer Привет! Извините, что всегда беспокою вас на протяжении всего SO. Но если мой модуль Pipe загружает .json с переводами, и я включаю этот модуль во все места, где он мне нужен... Я буду загружать этот .json много раз, верно? Есть ли способ избежать этого и по-прежнему иметь доступ к этому каналу перевода (и, следовательно, иметь доступ к модулю канала) во всем приложении? - person SrAxi; 06.04.2017
comment
Если код загрузки находится в службе, предоставленной в @NgModule() (и внедрить его в канал), вы можете управлять им в службе. Эта служба будет существовать в вашем приложении только один раз, независимо от того, как часто вы используете канал и выполняет ли служба вызов только один раз (см. также stackoverflow.com/questions/36271899/) Если ваш модуль Pipe загружен лениво, вам необходимо реализовать forRoot() и импортировать модуль в AppModule, чтобы обеспечить один экземпляр службы. - person Günter Zöchbauer; 06.04.2017
comment
@GünterZöchbauer Как всегда великолепно. Я посмотрю на это прямо сейчас. Спасибо! :D - person SrAxi; 06.04.2017