Utiliser un composant d'un autre module


200

J'ai l'application Angular 2.0.0 générée avec angular-cli.

Quand je crée un composant et que je l'ajoute au AppModuletableau des déclarations, tout va bien, cela fonctionne.

J'ai décidé de séparer les composants, j'ai donc créé un TaskModuleet un composant TaskCard. Maintenant, je veux utiliser le TaskCarddans l'un des composants de AppModule(le Boardcomposant).

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'ensemble du projet est disponible sur https://github.com/evgdim/angular2 (dossier kanban-board)

Qu'est-ce que je rate? Que dois-je faire pour l'utiliser TaskCardComponentdans BoardComponent?

Réponses:


391

La règle principale ici est que:

Les sélecteurs qui sont applicables lors de la compilation d'un modèle de composant sont déterminés par le module qui déclare ce composant, et la fermeture transitive des exportations des importations de ce module.

Alors, essayez de l'exporter:

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

Que dois-je exporter?

Exportez les classes déclarables que les composants des autres modules devraient pouvoir référencer dans leurs modèles. Ce sont vos cours publics. Si vous n'exportez pas une classe, elle reste privée, visible uniquement par les autres composants déclarés dans ce module.

La minute où vous créez un nouveau module, paresseux ou non, tout nouveau module et que vous y déclarez quoi que ce soit, ce nouveau module a un état propre (comme l'a dit Ward Bell dans https://devchat.tv/adv-in-angular/119 -aia-évitant-pièges-communs-en-angulaire2 )

Angulaire crée module transitif pour chacun des @NgModules.

Ce module collecte les directives qui ont été importées d'un autre module (si le module transitif du module importé a exporté des directives) ou déclarées dans le module actuel .

Lorsque angular compile le modèle qui appartient au module, Xil est utilisé les directives qui avaient été collectées dans 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

entrez la description de l'image ici

De cette façon, selon l'image ci-dessus

  • YComponentne peut pas utiliser ZComponentdans son modèle car le directivestableau de Transitive module Yne contient pas ZComponentcar YModulen'a pas importé ZModuledont le module transitif contient ZComponentdansexportedDirectives tableau.

  • Dans le XComponentmodèle que nous pouvons utiliser, ZComponentcar Transitive module Xpossède un tableau de directives qui contient, ZComponentcar XModuleimporte le module ( YModule) qui exporte le module (ZModule ) qui exporte la directiveZComponent

  • Dans le AppComponentmodèle, nous ne pouvons pas l'utiliser XComponentcar il AppModuleimporte XModulemais XModulen'exporte pas XComponent.

Voir également


13
Comment utiliser ce "TaskCardComponent" dans une définition de route dans le module d'importation?
jackOfAll

17
Quelle excellente réponse. Avez-vous créé le dessin? Si c'est le cas, je suis sans voix. Tout le monde n'a pas mis un tel effort dans ses réponses. Merci
Royi Namir

4
@Royi Oui, c'est ma photo :) Elle est basée sur le code source de github.com/angular/angular/blob/master/packages/compiler/src/…
yurzui

@yuruzi, je ne peux pas passer directement le noeud dom sans la référence stackoverflow.com/questions/47246638/… plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty

@yurzui ... Je ne comprends pas comment YComponent peut exporter ZModule, car je le vois comme un fichier séparé (y.module.ts) et il n'a aucune importation pour exporter un autre module (qui est z .module.ts) [supportez-moi si sa question de base]
OmGanesh

42

Vous devez à exportpartir de votre NgModule:

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

2
Cela fonctionne, jusqu'à ce que TaskModule soit importé dans AppModule. Il échoue lorsque TaskModule est chargé par lazyl.
Arun

40

(Angulaire 2 - Angulaire 7)

Le composant ne peut être déclaré que dans un seul module. Pour utiliser un composant d'un autre module, vous devez effectuer deux tâches simples:

  1. Exporter le composant dans l'autre module
  2. Importez l'autre module, dans le module actuel

1er module:

Avoir un composant (appelons-le: "ImportantCopmonent"), nous voulons le réutiliser dans la page du 2ème module.

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

2e module:

Réutilise le "ImportantCopmonent", en important le 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

Notez que pour créer un soi-disant "module de fonctionnalité", vous devez importer à l' CommonModuleintérieur. Ainsi, le code d'initialisation de votre module ressemblera à ceci:

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

Plus d'informations disponibles ici: https://angular.io/guide/ngmodule#create-the-feature-module


0

Tout ce que vous souhaitez utiliser à partir d'un autre module, placez-le simplement dans le tableau d'exportation . Comme ça-

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

0

Une grande et grande approche consiste à charger le module à partir d'un NgModuleFactory, vous pouvez charger un module à l'intérieur d'un autre module en appelant ceci:

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

Je l'ai eu d' ici .


NgModuleFactoryLoader est obsolète maintenant, alors quelle est sa meilleure façon alternative de faire cette chose?
Muzaffar Mahmood

-2

RÉSOLU COMMENT UTILISER UN COMPOSANT DÉCLARÉ DANS UN MODULE DANS UN AUTRE MODULE.

Basé sur l'explication de Royi Namir (merci beaucoup). Il manque une partie pour réutiliser un composant déclaré dans un module dans n'importe quel autre module pendant que le chargement différé est utilisé.

1er: Exportez le composant dans le module qui le contient:

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

2ème: Dans le module où vous souhaitez utiliser 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{}

Comme cela, le deuxième module importe le premier module qui importe et exporte le composant.

Lorsque nous importons le module dans le deuxième module, nous devons l'exporter à nouveau. Nous pouvons maintenant utiliser le premier composant du deuxième module.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.