Использовать компонент из другого модуля

201

У меня есть приложение Angular 2.0.0, созданное с помощью angular-cli.

Когда я создаю компонент и добавляю его в 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?

Евгений Димитров
источник

Ответы:

391

Основное правило здесь таково:

Селекторы, которые применяются во время компиляции шаблона компонента, определяются модулем, который объявляет этот компонент, и транзитивным закрытием экспортов импорта этого модуля.

Итак, попробуйте экспортировать это:

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

Что я должен экспортировать?

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

В тот момент, когда вы создаете новый модуль, ленивый или нет, любой новый модуль и что-то в него объявляете, этот новый модуль имеет чистое состояние (как сказал Уорд Белл в https://devchat.tv/adv-in-angular/119). -aia избегающего-общая-ловушка , в-angular2 )

Angular создает переходный модуль для каждого из @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потому что XModuleimport module ( YModule), который экспортирует module ( ZModule), который экспортирует директивуZComponent

  • В AppComponentшаблоне мы не можем использовать, XComponentпотому что AppModuleимпортирует, XModuleно XModuleне экспортирует XComponent.

Смотрите также

yurzui
источник
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{}
mxii
источник
2
Это работает, пока TaskModule не будет импортирован в AppModule. Сбой, когда TaskModule загружен.
Арун
40

(Угловой 2 - Угловой 7)

Компонент может быть объявлен только в одном модуле. Чтобы использовать компонент из другого модуля, вам нужно выполнить две простые задачи:

  1. Экспортировать компонент в другой модуль
  2. Импортируйте другой модуль в текущий модуль

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 { }
Эяль с
источник
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

Один большой и отличный подход заключается в загрузке модуля из a 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);
    });
}

Я получил это отсюда .

Gaspar
источник
NgModuleFactoryLoader устарел, так как лучше всего это сделать?
Музаффар Махмуд
-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{}

Таким образом, второй модуль импортирует первый модуль, который импортирует и экспортирует компонент.

Когда мы импортируем модуль во второй модуль, нам нужно экспортировать его снова. Теперь мы можем использовать первый компонент во втором модуле.

christianAV
источник