Usa componente da un altro modulo


199

Ho un'app Angular 2.0.0 generata con angular-cli.

Quando creo un componente e lo aggiungo AppModuleall'array delle dichiarazioni, va tutto bene, funziona.

Ho deciso di separare i componenti, quindi ho creato un TaskModulee un componente TaskCard. Ora voglio usare il TaskCardin uno dei componenti del AppModule(il 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{}

L'intero progetto è disponibile su https://github.com/evgdim/angular2 (cartella kanban-board)

Cosa mi sto perdendo? Che cosa devo fare per l'uso TaskCardComponentin BoardComponent?

Risposte:


390

La regola principale qui è che:

I selettori applicabili durante la compilazione di un modello di componente sono determinati dal modulo che dichiara quel componente e dalla chiusura transitiva delle esportazioni delle importazioni di quel modulo.

Quindi, prova a esportarlo:

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

Cosa dovrei esportare?

Esporta le classi dichiarabili che i componenti di altri moduli dovrebbero poter fare riferimento nei loro modelli. Queste sono le tue lezioni pubbliche. Se non esporti una classe, rimane privata, visibile solo agli altri componenti dichiarati in questo modulo.

Nel momento in cui crei un nuovo modulo, pigro o no, qualsiasi nuovo modulo e dichiari qualcosa in esso, quel nuovo modulo ha uno stato pulito (come diceva Ward Bell in https://devchat.tv/adv-in-angular/119 -aia-evitare-comuni-insidie-in-angolari2 )

Angolare crea un modulo transitivo per ciascuno di @NgModules.

Questo modulo raccoglie le direttive importate da un altro modulo (se il modulo transitivo del modulo importato ha esportato le direttive) o dichiarate nel modulo corrente .

Quando il modello di compilazione angolare appartiene al modulo X, vengono utilizzate le direttive raccolte in 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

inserisci qui la descrizione dell'immagine

In questo modo secondo l'immagine sopra

  • YComponentnon può usare ZComponentnel suo modello, perché directivesgamma di Transitive module Ynon contiene ZComponent, perché YModulenon ha importato ZModuleil cui modulo transitiva contiene ZComponentin exportedDirectivesarray.

  • All'interno del XComponentmodello possiamo usare ZComponentperché Transitive module Xha un array di direttive che contiene ZComponentperché XModuleimporta module ( YModule) che esporta module ( ZModule) che esporta direttivaZComponent

  • All'interno del AppComponentmodello non possiamo usare XComponentperché AppModuleimporta XModulema XModulenon esporta XComponent.

Guarda anche


13
Come posso utilizzare questo "TaskCardComponent" in una definizione di route nel modulo Importing?
jackOfTutti il

17
Che risposta eccezionale. Hai creato il disegno? Se è così, sono senza parole. Non tutti mettono tale sforzo nelle loro risposte. Grazie
Royi Namir il

4
@Royi Sì, questa è la mia foto :) È basata sul codice sorgente da github.com/angular/angular/blob/master/packages/compiler/src/…
yurzui

@yuruzi, non posso passare il nodo dom direttamente senza il riferimento stackoverflow.com/questions/47246638/... plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty

@yurzui ... Non capisco come può YComponent esportare ZModule, visto che lo vedo come un file separato (y.module.ts) e non ha alcuna importazione in modo da esportare altri moduli (che è z .module.ts) [portami se è la sua domanda di base]
OmGanesh,

42

Devi exportfarlo dal tuo NgModule:

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

2
Funziona fino a quando TaskModule non viene importato in AppModule. Non riesce quando TaskModule è lazyload.
Arun,

40

(Angolare 2 - Angolare 7)

Il componente può essere dichiarato solo in un singolo modulo. Per utilizzare un componente da un altro modulo, è necessario eseguire due semplici operazioni:

  1. Esporta il componente nell'altro modulo
  2. Importa l'altro modulo, nel modulo corrente

1 ° modulo:

Avere un componente (chiamiamolo: "ImportantCopmonent"), vogliamo riutilizzarlo nella pagina del 2 ° modulo.

@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 ° modulo:

Riutilizza "ImportantCopmonent" importando 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

Si noti che per creare un cosiddetto "modulo funzionale", è necessario importarlo CommonModuleal suo interno. Quindi, il codice di inizializzazione del modulo sarà simile al seguente:

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

Maggiori informazioni disponibili qui: https://angular.io/guide/ngmodule#create-the-feature-module


0

Qualunque cosa tu voglia usare da un altro modulo, inseriscilo nell'array di esportazione . Come questo-

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

0

Un approccio grande e grande è quello di caricare il modulo da un NgModuleFactory, è possibile caricare un modulo all'interno di un altro modulo chiamando questo:

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

L'ho preso da qui .


NgModuleFactoryLoader è obsoleto, quindi qual è il suo modo migliore alternativo per fare questa cosa?
Muzaffar Mahmood,

-2

RISOLTO COME USARE UN COMPONENTE DICHIARATO IN UN MODULO IN ALTRI MODULI.

Basato sulla spiegazione di Royi Namir (Grazie mille). È presente una parte mancante per riutilizzare un componente dichiarato in un modulo in qualsiasi altro modulo mentre viene utilizzato il caricamento lento.

1 °: esporta il componente nel modulo che lo contiene:

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

2 °: nel modulo in cui si desidera utilizzare 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{}

In questo modo il secondo modulo importa il primo modulo che importa ed esporta il componente.

Quando importiamo il modulo nel secondo modulo, dobbiamo esportarlo di nuovo. Ora possiamo usare il primo componente nel secondo modulo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.