Використовуйте компонент з іншого модуля


199

У мене є програма Angular 2.0.0, що генерується з кутовим кліном.

Коли я створюю компонент і додаю його до AppModuleмасиву декларацій, це все добре, він працює.

Я вирішив розділити компоненти, тому створив 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?

Відповіді:


389

Тут головне правило:

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

Отже, спробуйте експортувати його:

@NgModule({
  declarations: [TaskCardComponent],
  imports: [MdCardModule],
  exports: [TaskCardComponent] <== this line
})
export class TaskModule{}

Що я повинен експортувати?

Експортуйте класи, які підлягають виявленню, на компоненти яких в інших модулях повинні мати можливість посилатися у своїх шаблонах. Це ваші громадські заняття. Якщо ви не експортуєте клас, він залишається приватним, видимим лише для іншого компонента, декларованого в цьому модулі.

У хвилину, коли ви створюєте новий модуль, лінивий чи ні, будь-який новий модуль і декларуєте що-небудь в ньому, той новий модуль має чистий стан (як сказав Уорд Белл на https://devchat.tv/adv-in-angular/119 -aia-уникнення-загальні підводні камені-у-куті2 )

Кутовий створює перехідний модуль для кожного з @NgModules.

Цей модуль збирає директиви, які імпортуються з іншого модуля (якщо перехідний модуль імпортного модуля експортував директиви) або оголошені в поточному модулі .

Коли кутовий компілює шаблон, що належить модулю 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) , що експорт модуль (ZModule ), що директиву про експортZComponent

  • У AppComponentшаблоні ми не можемо використовувати, XComponentоскільки AppModuleімпортуємо, XModuleале XModuleне експортуємоXComponent .

Дивитися також


13
Як я можу використовувати цей "TaskCardComponent" для визначення маршруту в модулі імпорту?
jackOfAll

17
Яка чудова відповідь. Ви створили малюнок? Якщо так, я без мови. Не всі доклали таких зусиль у своїх відповідях. Дякую
Рой Намір

4
@Royi Так, це моя картинка :) Він заснований на вихідному коді від github.com/angular/angular/blob/master/packages/compiler/src/…
yurzui

@yuruzi, я не можу передати вузол DOM безпосередньо без посилання stackoverflow.com/questions/47246638 / ... plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty

@yurzui ... Я не розумію, як YComponent може експортувати ZModule, оскільки я бачу це як окремий файл (y.module.ts), і він не має жодного імпорту, щоб експортувати інший модуль (який є z .module.ts) [візьміть мене за його основне запитання]
OmGanesh

42

Ви маєте exportце від свого NgModule:

@NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule],
  providers: []
})
export class TaskModule{}

2
Це працює, поки TaskModule не імпортується в AppModule. Виходить з ладу, коли TaskModule ледачий.
Арун

40

(Кутовий 2 - Кутовий 7)

Компонент може бути оголошений лише в одному модулі. Для того, щоб використовувати компонент з іншого модуля, потрібно виконати дві прості задачі:

  1. Експортуйте компонент в інший модуль
  2. Імпортуйте інший модуль у поточний модуль

1-й модуль:

Маємо компонент (давайте називати його: "Важливий Комонент"), ми хочемо повторно використовувати його на сторінці 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 { }

2

Зауважте, що для створення так званого "функціонального модуля" вам потрібно імпортувати 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


0

Що б ви не хотіли використовувати з іншого модуля, просто покладіть його в експортний масив . Подобається це-

 @NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule]
})

0

Один великий і чудовий підхід - це завантаження модуля з 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);
    });
}

Я отримав це від звідси .


NgModuleFactoryLoader зараз застарілий, тож який найкращий альтернативний спосіб зробити це?
Muzaffar Mahmood

-2

РІШЕНО ЯК ВИКОРИСТОВУВАТИ КОМПОНЕНТ, ЗАЯВЛЕНИЙ В МОДУЛІ В ІНШОМУ МОДУЛІ.

На основі пояснення Роя Наміра (велике спасибі). Існує відсутність частини для повторного використання компонента, оголошеного в модулі, в будь-якому іншому модулі, коли використовується ледаче завантаження.

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{}

Так, другий модуль імпортує перший модуль, який імпортує та експортує компонент.

Коли ми імпортуємо модуль у другому модулі, нам потрібно експортувати його ще раз. Тепер ми можемо використовувати перший компонент у другому модулі.

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