Usar componente de outro módulo

199

Eu tenho o aplicativo Angular 2.0.0 gerado com angular-cli.

Quando crio um componente e o adiciono à AppModulematriz de declarações, tudo fica bem, funciona.

Decidi separar os componentes, então criei um TaskModulee um componente TaskCard. Agora eu quero usar o TaskCardem um dos componentes do AppModule(o Boardcomponente).

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

Todo o projeto está disponível em https://github.com/evgdim/angular2 (pasta kanban-board)

o que estou perdendo? O que eu tenho que fazer para uso TaskCardComponentem BoardComponent?

Evgeni Dimitrov
fonte

Respostas:

390

A regra principal aqui é que:

Os seletores aplicáveis ​​durante a compilação de um modelo de componente são determinados pelo módulo que declara esse componente e pelo fechamento transitivo das exportações das importações desse módulo.

Então, tente exportá-lo:

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

O que devo exportar?

Exporte classes declaráveis ​​que os componentes de outros módulos devem poder fazer referência em seus modelos. Estas são suas aulas públicas. Se você não exportar uma classe, ela permanecerá privada, visível apenas para outro componente declarado neste módulo.

No minuto em que você cria um novo módulo, preguiçoso ou não, qualquer novo módulo e declara algo nele, esse novo módulo tem um estado limpo (como Ward Bell disse em https://devchat.tv/adv-in-angular/119 -aia-evitando-armadilhas-comuns-em-angular2 )

Angular cria módulo transitivo para cada um dos @NgModules.

Este módulo coleta diretivas importadas de outro módulo (se o módulo transitivo do módulo importado tiver exportado diretivas) ou declaradas no módulo atual .

Quando o modelo de compilação angular que pertence ao módulo X, são usadas as diretivas que foram coletadas no 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

insira a descrição da imagem aqui

Desta forma, de acordo com a imagem acima

  • YComponentnão pode usar ZComponentem seu modelo porque a directivesmatriz de Transitive module Ynão contém ZComponentporque YModulenão importou ZModulecujo módulo transitivo contenha ZComponentna exportedDirectivesmatriz.

  • No XComponentmodelo, podemos usar ZComponentporque Transitive module Xpossui uma matriz de diretivas que contém ZComponentporque XModuleimporta module ( YModule) que exporta module ( ZModule) que exporta diretivaZComponent

  • No AppComponentmodelo, não podemos usar XComponentporque AppModuleimporta, XModulemas XModulenão exporta XComponent.

Veja também

yurzui
fonte
13
Como uso esse "TaskCardComponent" em uma definição de rota no módulo Importando?
precisa
17
Que ótima resposta. Você criou o desenho? Se assim for, estou sem palavras. Nem todo mundo coloca tanto esforço em suas respostas. Obrigado
Royi Namir
4
@Royi Sim, esta é a minha imagem :) É baseado no código-fonte do github.com/angular/angular/blob/master/packages/compiler/src/...
yurzui
@yuruzi, eu não posso passar o nó dom diretamente sem a referência stackoverflow.com/questions/47246638/… plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty
@yurzui ... Eu não entendo como o YComponent pode exportar o ZModule, pois estou vendo isso como um arquivo separado (y.module.ts) e não tem nenhuma importação para exportar outro módulo (que é z .module.ts) [suportar-me se a sua pergunta básica]
OmGanesh
42

Você precisa exportdisso do seu NgModule:

@NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule],
  providers: []
})
export class TaskModule{}
mxii
fonte
2
Isso funciona, até que o TaskModule seja importado no AppModule. Falha quando TaskModule é carregado com preguiça.
Arun
40

(Angular 2 - Angular 7)

O componente pode ser declarado apenas em um único módulo. Para usar um componente de outro módulo, você precisa executar duas tarefas simples:

  1. Exporte o componente no outro módulo
  2. Importe o outro módulo para o módulo atual

1º módulo:

Tenha um componente (vamos chamá-lo: "ImportantCopmonent"), queremos reutilizar na página do 2º módulo.

@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º Módulo:

Reutiliza o "ImportantCopmonent", importando o 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 { }
Eyal c
fonte
2

Observe que, para criar o chamado "módulo de recurso", você precisa importar CommonModuledentro dele. Portanto, seu código de inicialização do módulo será semelhante a este:

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

Mais informações disponíveis aqui: https://angular.io/guide/ngmodule#create-the-feature-module

não pare
fonte
0

Tudo o que você deseja usar de outro módulo, basta colocá-lo na matriz de exportação . Como isso-

 @NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule]
})
Abhishek Chandel
fonte
0

Uma abordagem grande e ótima é carregar o módulo de a NgModuleFactory, você pode carregar um módulo dentro de outro módulo chamando isto:

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);
    });
}

Eu peguei isso daqui .

Gaspar
fonte
NgModuleFactoryLoader está obsoleto agora. Qual é a melhor maneira alternativa de fazer isso?
Muzaffar Mahmood
-2

RESOLVIDO COMO USAR UM COMPONENTE DECLARADO EM UM MÓDULO EM OUTRO MÓDULO.

Baseado na explicação de Royi Namir (Muito obrigado). Há uma peça que falta para reutilizar um componente declarado em um módulo em qualquer outro módulo enquanto o carregamento lento é usado.

1º: exporte o componente no módulo que o contém:

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

2º: No módulo em que você deseja usar o 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{}

Assim, o segundo módulo importa o primeiro módulo que importa e exporta o componente.

Quando importamos o módulo no segundo módulo, precisamos exportá-lo novamente. Agora podemos usar o primeiro componente no segundo módulo.

christianAV
fonte