Angular 2 Используйте компонент из другого модуля

У меня есть 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?

Ответ 1

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

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

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

@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

enter image description here

Таким образом, согласно изображению выше

  • 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.

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

Ответ 2

Вы должны export от своего NgModule:

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

Ответ 3

(Angular 2 - Angular 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 { }

Ответ 4

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

Ответ 5

Независимо от того, что вы хотите использовать из другого модуля, просто поместите его в массив export. Как это -

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

Ответ 6

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

На основании объяснения Ройи Намира (Большое спасибо). Отсутствует часть для повторного использования компонента, объявленного в модуле, в любом другом модуле, пока используется отложенная загрузка.

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

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

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

Ответ 7

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

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

Ответ 8

@yurzui у вас есть правильное решение и спасибо за объяснение.

У меня была проблема и эта строка:

экспорт: [Компонент] решил.