Verwenden Sie eine Komponente aus einem anderen Modul


199

Ich habe Angular 2.0.0 App mit Angular-Cli generiert.

Wenn ich eine Komponente erstelle und hinzufüge AppModule Deklarationsarray ist alles in Ordnung, es funktioniert.

Ich habe mich entschieden, die Komponenten zu trennen, also habe ich eine TaskModuleund eine Komponente erstellt TaskCard. Jetzt möchte ich die TaskCardin einer der Komponenten der AppModule(der BoardKomponente) verwenden.

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

Das gesamte Projekt ist unter https://github.com/evgdim/angular2 verfügbar (Kanban-Board-Ordner)

Was vermisse ich? Was habe ich zu verwenden zu tun , TaskCardComponentin BoardComponent?

Antworten:


389

Die Hauptregel hier ist:

Die Selektoren, die während der Kompilierung einer Komponentenvorlage anwendbar sind, werden durch das Modul bestimmt, das diese Komponente deklariert, und durch den vorübergehenden Abschluss der Exporte der Importe dieses Moduls.

Versuchen Sie also, es zu exportieren:

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

Was soll ich exportieren?

Exportieren Sie deklarierbare Klassen, auf die Komponenten in anderen Modulen in ihren Vorlagen verweisen können sollten. Dies sind Ihre öffentlichen Klassen. Wenn Sie eine Klasse nicht exportieren, bleibt sie privat und nur für andere in diesem Modul deklarierte Komponenten sichtbar.

Sobald Sie ein neues Modul erstellen, ob faul oder nicht, ein neues Modul und etwas darin deklarieren, hat dieses neue Modul einen sauberen Zustand (wie Ward Bell in https://devchat.tv/adv-in-angular/119 sagte -aia-Vermeidung-häufiger-Fallstricke-im-Winkel2 )

Angular erstellt ein transitives Modul für jedes von @NgModules.

Dieses Modul sammelt Anweisungen, die entweder aus einem anderen Modul importiert wurden (wenn das transitive Modul des importierten Moduls Anweisungen exportiert hat) oder im aktuellen Modul deklariert wurden .

Wenn Angular eine Vorlage kompiliert, die zum Modul Xgehört, werden die Anweisungen verwendet, die in X.transitiveModule.directives gesammelt wurden .

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

Geben Sie hier die Bildbeschreibung ein

Auf diese Weise gemäß dem obigen Bild

  • YComponentkann nicht ZComponentin seiner Vorlage verwendet werden, da das directivesArray von Transitive module Ynicht enthält, ZComponentweil YModulenicht importiert wurde, ZModuledessen transitives Modul ZComponentim exportedDirectivesArray enthält .

  • Innerhalb der XComponentVorlage können wir verwenden, ZComponentweil Transitive module Xhat Anweisungen Array, das enthält, ZComponentweil XModuleModul ( YModule) importiert , das Modul ( ZModule) exportiert, das Direktive exportiertZComponent

  • Innerhalb der AppComponentVorlage können wir nicht verwenden, XComponentweil AppModuleimportiert XModule, XModuleaber nicht exportiert XComponent.

Siehe auch


13
Wie verwende ich diese "TaskCardComponent" in einer Routendefinition im Importmodul?
JackOfAll

17
Was für eine großartige Antwort. Hast du die Zeichnung erstellt? Wenn ja, bin ich sprachlos. Nicht jeder hat solche Anstrengungen in seine Antworten gesteckt. Vielen Dank
Royi Namir

4
@ Royi Ja, das ist mein Bild :) Es basiert auf dem Quellcode von github.com/angular/angular/blob/master/packages/compiler/src/…
yurzui

@yuruzi, ich kann den Dom-Knoten nicht direkt ohne die Referenz stackoverflow.com/questions/47246638/… plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty

@yurzui ... Ich verstehe nicht, wie YComponent ZModule exportieren kann, da ich das als separate Datei (y.module.ts) sehe und keinen Import habe, um ein anderes Modul (z .module.ts) [tragen Sie mich, wenn seine grundlegende Frage]
OmGanesh

42

Sie müssen exportes von Ihrem NgModule:

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

2
Dies funktioniert, bis TaskModule in AppModule importiert wird. Es schlägt fehl, wenn TaskModule lazyloaded ist.
Arun

40

(Winkel 2 - Winkel 7)

Die Komponente kann nur in einem einzelnen Modul deklariert werden. Um eine Komponente aus einem anderen Modul zu verwenden, müssen Sie zwei einfache Aufgaben ausführen:

  1. Exportieren Sie die Komponente in das andere Modul
  2. Importieren Sie das andere Modul in das aktuelle Modul

1. Modul:

Haben Sie eine Komponente (nennen wir sie "ImportantCopmonent"), die wir auf der Seite des 2. Moduls wiederverwenden möchten.

@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. Modul:

Verwendet das "ImportantCopmonent" erneut, indem das FirstPageModule importiert wird

@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

Beachten Sie, dass Sie zum Erstellen eines sogenannten "Feature-Moduls" darin importieren müssen CommonModule. Ihr Modulinitialisierungscode sieht also folgendermaßen aus:

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

Weitere Informationen finden Sie hier: https://angular.io/guide/ngmodule#create-the-feature-module


0

Was auch immer Sie von einem anderen Modul verwenden möchten, fügen Sie es einfach in das Export-Array ein . So was-

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

0

Ein großer und großartiger Ansatz besteht darin, das Modul von einem zu laden. NgModuleFactorySie können ein Modul in ein anderes Modul laden, indem Sie Folgendes aufrufen:

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

Ich habe das von hier bekommen .


NgModuleFactoryLoader ist jetzt veraltet. Was ist also die beste Alternative, um dies zu tun?
Muzaffar Mahmood

-2

Gelöst, wie eine Komponente verwendet werden soll, die in einem Modul in einem anderen Modul angegeben ist.

Basierend auf der Erklärung von Royi Namir (Vielen Dank). Es fehlt ein Teil, um eine in einem Modul deklarierte Komponente in einem anderen Modul wiederzuverwenden, während das verzögerte Laden verwendet wird.

1. Exportieren Sie die Komponente in das Modul, das sie enthält:

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

2. In dem Modul, in dem Sie TaskCardComponent verwenden möchten:

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

Auf diese Weise importiert das zweite Modul das erste Modul, das die Komponente importiert und exportiert.

Wenn wir das Modul im zweiten Modul importieren, müssen wir es erneut exportieren. Jetzt können wir die erste Komponente im zweiten Modul verwenden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.