У меня есть Angular 2 (версия 2.0.0 - окончательное) приложение, созданное с помощью angular -cli.
Когда я создаю компонент и добавляю его в массив AppModule
declarations, все это хорошо, он работает.
Я решил разделить компоненты, поэтому создал TaskModule
и компонент TaskCard
. Теперь я хочу использовать TaskCard
в одном из компонентов AppModule
(компонент Board
).
AppModule:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { BoardComponent } from './board/board.component';
import { LoginComponent } from './login/login.component';
import { MdButtonModule } from '@angular2-material/button';
import { MdInputModule } from '@angular2-material/input';
import { MdToolbarModule } from '@angular2-material/toolbar';
import { routing, appRoutingProviders} from './app.routing';
import { PageNotFoundComponent } from './page-not-found/page-not-found.component';
import { UserService } from './services/user/user.service';
import { TaskModule } from './task/task.module';
@NgModule({
declarations: [
AppComponent,
BoardComponent,// I want to use TaskCard in this component
LoginComponent,
PageNotFoundComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule,
MdButtonModule,
MdInputModule,
MdToolbarModule,
routing,
TaskModule // TaskCard is in this module
],
providers: [UserService],
bootstrap: [AppComponent]
})
export class AppModule { }
TaskModule:
import { NgModule } from '@angular/core';
import { TaskCardComponent } from './task-card/task-card.component';
import { MdCardModule } from '@angular2-material/card';
@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
providers: []
})
export class TaskModule{}
Весь проект доступен на https://github.com/evgdim/angular2 (папка kanban-board)
Что мне не хватает? Что мне нужно сделать, чтобы использовать TaskCardComponent
в BoardComponent
?
Основное правило здесь таково:
Селекторы, которые применяются во время компиляции шаблона компонента, определяются модулем, который объявляет этот компонент, и транзитивным закрытием экспорта этого модуля.
Итак, попробуйте экспортировать это:
@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
exports: [TaskCardComponent] <== this line
})
export class TaskModule{}
Что я должен экспортировать?
Экспортируйте декларируемые классы, на которые компоненты в других модулях должны ссылаться в своих шаблонах. Это ваши публичные занятия. Если вы не экспортируете класс, он остается закрытым, видимым только для другого компонента, объявленного в этом модуле.
В тот момент, когда вы создаете новый модуль, ленивый или нет, любой новый модуль и что-то в него объявляете, этот новый модуль находится в чистом состоянии (как сказал Уорд Белл в https://devchat.tv/adv-in-angular/119). -aia-уклонение-общие-подводные камни2)
Angular создает транзитивный модуль для каждого из @NgModule
s.
Этот модуль собирает директивы, которые либо импортированы из другого модуля (если транзитивный модуль импортированного модуля имеет экспортированные директивы), либо объявлены в текущем модуле.
Когда угловая компилирует шаблон, который принадлежит модулю X
используются те директивы, которые были собраны в X.transitiveModule.directives.
compiledTemplate = new CompiledTemplate(
false, compMeta.type, compMeta, ngModule, ngModule.transitiveModule.directives);
https://github.com/angular/angular/blob/4.2.x/packages/compiler/src/jit/compiler.ts#L250-L251
Таким образом, согласно изображению выше
YComponent
не может использовать ZComponent
в шаблоне, поскольку directives
массив Transitive module Y
не содержит ZComponent
потому YModule
не импортирован ZModule
которого транзитивно модуль содержит ZComponent
в exportedDirectives
массиве.
В шаблоне XComponent
мы можем использовать ZComponent
потому что Transitive module X
имеет массив директив, который содержит ZComponent
потому что XModule
импорта YModule
(YModule
), который экспортирует модуль (ZModule
), который экспортирует директиву ZComponent
В шаблоне AppComponent
мы не можем использовать XComponent
потому что AppModule
импортирует XModule
но XModule
не экспортирует XComponent
.
Смотрите также
Вы должны export
от своего NgModule
:
@NgModule({
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule],
providers: []
})
export class TaskModule{}
Обратите внимание, что для создания так называемого "функционального модуля" вам нужно импортировать CommonModule
внутри него. Итак, код инициализации вашего модуля будет выглядеть следующим образом:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TaskCardComponent } from './task-card/task-card.component';
import { MdCardModule } from '@angular2-material/card';
@NgModule({
imports: [
CommonModule,
MdCardModule
],
declarations: [
TaskCardComponent
],
exports: [
TaskCardComponent
]
})
export class TaskModule { }
Дополнительная информация доступна здесь: https://angular.io/guide/ngmodule#create-the-feature-module
(Угловой 2 - Угловой 6)
Компонент может быть объявлен только в одном модуле. Чтобы использовать компонент из другого модуля, вам нужно выполнить две простые задачи:
1-й модуль:
Имеем компонент (назовем его "ImportantCopmonent"), который мы хотим повторно использовать на странице 2-го модуля.
@NgModule({
declarations: [
FirstPage,
ImportantCopmonent // <-- Enable using the component html tag in current module
],
imports: [
IonicPageModule.forChild(NotImportantPage),
TranslateModule.forChild(),
],
exports: [
FirstPage,
ImportantCopmonent // <--- Enable using the component in other modules
]
})
export class FirstPageModule { }
2-й модуль:
Повторно использует "ImportantCopmonent", импортируя FirstPageModule
@NgModule({
declarations: [
SecondPage,
Example2ndComponent,
Example3rdComponent
],
imports: [
IonicPageModule.forChild(SecondPage),
TranslateModule.forChild(),
FirstPageModule // <--- this Imports the source module, with its exports
],
exports: [
SecondPage,
]
})
export class SecondPageModule { }
Один большой и отличный подход заключается в загрузке модуля из NgModuleFactory
Вы можете загрузить модуль внутри другого модуля, вызвав это:
constructor(private loader: NgModuleFactoryLoader, private injector: Injector) {}
loadModule(path: string) {
this.loader.load(path).then((moduleFactory: NgModuleFactory<any>) => {
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
this.lazyOutlet.createComponent(compFactory);
});
}
Я получил это отсюда.
РЕШЕНО, КАК ИСПОЛЬЗОВАТЬ КОМПОНЕНТ, ЗАЯВЛЕННЫЙ В МОДУЛЕ В ДРУГОМ МОДУЛЕ.
На основании объяснения Ройи Намира (Большое спасибо). Отсутствует часть для повторного использования компонента, объявленного в модуле, в любом другом модуле, пока используется отложенная загрузка.
1-й: экспортируйте компонент в модуль, который содержит его:
@NgModule({
declarations: [TaskCardComponent],
imports: [MdCardModule],
exports: [TaskCardComponent] <== this line
})
export class TaskModule{}
2-й: в модуле, где вы хотите использовать TaskCardComponent:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MdCardModule } from '@angular2-material/card';
@NgModule({
imports: [
CommonModule,
MdCardModule
],
providers: [],
exports:[ MdCardModule ] <== this line
})
export class TaskModule{}
Таким образом, второй модуль импортирует первый модуль, который импортирует и экспортирует компонент.
Когда мы импортируем модуль во второй модуль, нам нужно экспортировать его снова. Теперь мы можем использовать первый компонент во втором модуле.
MdCardModule
остается для меня путаницей
Независимо от того, что вы хотите использовать из другого модуля, просто поместите его в массив export. Как это -
@NgModule({
declarations: [TaskCardComponent],
exports: [TaskCardComponent],
imports: [MdCardModule]
})