Usar componente de otro módulo

199

Tengo la aplicación Angular 2.0.0 generada con angular-cli.

Cuando creo un componente y lo agrego a AppModulela matriz de declaraciones, todo está bien, funciona.

Decidí separar los componentes, así que creé un TaskModuley un componente TaskCard. Ahora quiero usar el TaskCarden uno de los componentes de AppModule(el 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 el proyecto está disponible en https://github.com/evgdim/angular2 (carpeta kanban-board)

¿Qué me estoy perdiendo? ¿Qué tengo que hacer para su uso TaskCardComponenten BoardComponent?

Evgeni Dimitrov
fuente

Respuestas:

390

La regla principal aquí es que:

Los selectores que son aplicables durante la compilación de una plantilla de componente están determinados por el módulo que declara ese componente y el cierre transitivo de las exportaciones de las importaciones de ese módulo.

Entonces, intenta exportarlo:

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

¿Qué debo exportar?

Exporte clases declarables a las que los componentes de otros módulos deberían poder hacer referencia en sus plantillas. Estas son tus clases públicas. Si no exporta una clase, permanece privada, visible solo para otro componente declarado en este módulo.

En el momento en que crea un nuevo módulo, perezoso o no, cualquier módulo nuevo y declara cualquier cosa en él, ese nuevo módulo tiene un estado limpio (como dijo Ward Bell en https://devchat.tv/adv-in-angular/119 -aia-evitar-trampas-comunes-en-angular2 )

Angular crea un módulo transitivo para cada uno de los @NgModules.

Este módulo recopila directivas que importaron de otro módulo (si el módulo transitivo del módulo importado ha exportado directivas) o se declararon en el módulo actual .

Cuando la plantilla de compilaciones angulares que pertenece al módulo Xse usa las directivas que se habían recopilado en 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

ingrese la descripción de la imagen aquí

De esta manera según la imagen de arriba

  • YComponentno se puede usar ZComponenten su plantilla porque la directivesmatriz de Transitive module Yno contiene ZComponentporque YModuleno ha importado qué ZModulemódulo transitivo contiene ZComponenten la exportedDirectivesmatriz.

  • Dentro de la XComponentplantilla podemos usar ZComponentporque Transitive module Xtiene una matriz de directivas que contiene ZComponentporque XModuleimporta el módulo ( YModule) que exporta el módulo ( ZModule) que exporta la directivaZComponent

  • Dentro de la AppComponentplantilla no podemos usar XComponentporque AppModuleimporta XModulepero XModuleno exporta XComponent.

Ver también

yurzui
fuente
13
¿Cómo uso este "TaskCardComponent" en una definición de ruta en el módulo Importar?
jackOfAll
17
Que gran respuesta. ¿Creaste el dibujo? Si es así, estoy sin palabras. No todos ponen tanto esfuerzo en sus respuestas. Gracias
Royi Namir
44
@Royi Sí, esta es mi foto :) Está basada en el código fuente de github.com/angular/angular/blob/master/packages/compiler/src/…
yurzui
@yuruzi, no puedo pasar el nodo dom directamente sin la referencia stackoverflow.com/questions/47246638/… plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty
@yurzui ... No entiendo cómo puede YComponent exportar ZModule, ya que lo veo como un archivo separado (y.module.ts) y no tiene ninguna importación para exportar otro módulo (que es z .module.ts) [abrázame si es su pregunta básica]
OmGanesh
42

Tienes que exporthacerlo desde tu NgModule:

@NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule],
  providers: []
})
export class TaskModule{}
mxii
fuente
2
Esto funciona, hasta que TaskModule se importe en AppModule. Falla cuando TaskModule se carga de forma diferida.
Arun
40

(Angular 2 - Angular 7)

El componente solo se puede declarar en un único módulo. Para utilizar un componente de otro módulo, debe realizar dos tareas simples:

  1. Exportar el componente en el otro módulo
  2. Importa el otro módulo al módulo actual

1er módulo:

Tener un componente (llamémoslo: "ImportanteCopmonente"), queremos reutilizarlo en la página del segundo 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 { }

2do módulo:

Reutiliza el "ImportanteCopmonente", importando el 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
fuente
2

Tenga en cuenta que para crear un denominado "módulo de características", debe importar CommonModuledentro de él. Entonces, el código de inicialización de su módulo se verá así:

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

Más información disponible aquí: https://angular.io/guide/ngmodule#create-the-feature-module

no te detengas
fuente
0

Lo que quiera usar de otro módulo, simplemente póngalo en la matriz de exportación . Me gusta esto-

 @NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule]
})
Lámpara Abhishek
fuente
0

Un enfoque grande y excelente es cargar el módulo desde a NgModuleFactory, puede cargar un módulo dentro de otro módulo llamando a esto:

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

Tengo esto de aquí .

Gaspar
fuente
NgModuleFactoryLoader está en desuso ahora, ¿cuál es su mejor forma alternativa de hacer esto?
Muzaffar Mahmood
-2

RESUELTO CÓMO USAR UN COMPONENTE DECLARADO EN UN MÓDULO EN OTRO MÓDULO.

Basado en la explicación de Royi Namir (Muchas gracias). Falta una parte para reutilizar un componente declarado en un Módulo en cualquier otro módulo mientras se usa la carga diferida.

Primero: Exportar el componente en el módulo que lo contiene:

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

2do: En el módulo donde desea usar 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{}

De este modo, el segundo módulo importa el primer módulo que importa y exporta el componente.

Cuando importamos el módulo en el segundo módulo, necesitamos exportarlo nuevamente. Ahora podemos usar el primer componente en el segundo módulo.

christianAV
fuente