Użyj komponentu z innego modułu

199

Mam aplikację Angular 2.0.0 wygenerowaną z angular-cli.

Kiedy tworzę komponent i dodam go do AppModuletablicy deklaracji, wszystko jest w porządku, działa.

Zdecydowałem się oddzielić komponenty, więc utworzyłem a TaskModulei komponent TaskCard. Teraz chcę użyć TaskCardw jednym ze składników AppModule( Boardskładnika).

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

Moduł zadań:

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

Cały projekt jest dostępny na https://github.com/evgdim/angular2 (folder kanban-board)

czego mi brakuje? Co muszę zrobić, aby użytku TaskCardComponentw BoardComponent?

Jewgienij Dimitrow
źródło

Odpowiedzi:

389

Główną zasadą jest tutaj:

Selektory, które mają zastosowanie podczas kompilacji szablonu komponentu, są określane przez moduł deklarujący ten komponent oraz przechodnie przechowywanie eksportu importów tego modułu.

Spróbuj go wyeksportować:

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

Co powinienem eksportować?

Eksportuj deklarowalne klasy, do których komponenty w innych modułach powinny mieć dostęp w swoich szablonach. To są twoje publiczne klasy. Jeśli nie eksportujesz klasy, pozostaje ona prywatna, widoczna tylko dla innych komponentów zadeklarowanych w tym module.

Gdy tylko utworzysz nowy moduł, leniwy czy nie, nowy moduł i zadeklarujesz coś w nim, ten nowy moduł ma czysty stan (jak powiedział Ward Bell w https://devchat.tv/adv-in-angular/119 -aia-unikanie-wspólne-pułapki-w-kątowe2 )

Angular tworzy moduł przechodni dla każdego z @NgModules.

Ten moduł zbiera dyrektywy, które albo zostały zaimportowane z innego modułu (jeśli moduł przechodni importowanego modułu ma wyeksportowane dyrektywy) lub zadeklarowane w bieżącym module .

Kiedy kątowy szablon kompiluje należący do modułu X, używane są te dyrektywy, które zostały zebrane w 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

wprowadź opis zdjęcia tutaj

W ten sposób zgodnie z powyższym obrazkiem

  • YComponentnie można użyć ZComponentw szablonie, ponieważ directivestablica Transitive module Ynie zawiera, ZComponentponieważ YModulenie zaimportowano, ZModulektórego moduł przechodni zawiera ZComponentw exportedDirectivestablicy.

  • W XComponentszablonie możemy użyć, ZComponentponieważ Transitive module Xma tablicę dyrektyw, która zawiera ZComponentponieważ XModulemoduł importu ( YModule), który eksportuje moduł ( ZModule), który eksportuje dyrektywęZComponent

  • W AppComponentszablonie nie możemy używać, XComponentponieważ AppModuleimportuje, XModuleale XModulenie eksportuje XComponent.

Zobacz też

yurzui
źródło
13
Jak korzystać z tego „TaskCardComponent” w definicji trasy w module Importowanie?
jackOfAll
17
Co za świetna odpowiedź. Czy stworzyłeś rysunek? Jeśli tak, to zaniemówiłem. Nie wszyscy wkładają taki wysiłek w swoje odpowiedzi. Dziękuję
Royi Namir,
4
@Royi Tak, to moje zdjęcie :) Opiera się na kodzie źródłowym z github.com/angular/angular/blob/master/packages/compiler/src/…
yurzui
@yuruzi, nie mogę przejść węzeł DOM bezpośrednio bez odniesienia stackoverflow.com/questions/47246638/... plnkr.co/edit/DnnjFBa3HLzFKNIdE4q5?p=preview
Karty
@yurzui ... Nie rozumiem, jak YComponent może eksportować ZModule, ponieważ widzę to jako osobny plik (y.module.ts) i nie ma żadnego importu, aby wyeksportować inny moduł (który jest z .module.ts) [no to mi podstawowe pytanie]
OmGanesh
42

Musisz to exportzrobić ze swojego NgModule:

@NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule],
  providers: []
})
export class TaskModule{}
MXII
źródło
2
Działa to do momentu zaimportowania TaskModule do AppModule. Nie powiedzie się, gdy moduł zadań jest leniwie załadowany.
Arun
40

(Angular 2 - Angular 7)

Element można zadeklarować tylko w jednym module. Aby użyć komponentu z innego modułu, musisz wykonać dwa proste zadania:

  1. Wyeksportuj komponent do drugiego modułu
  2. Zaimportuj drugi moduł do bieżącego modułu

1. moduł:

Posiadamy komponent (nazwijmy go: „ImportantCopmonent”), chcemy ponownie użyć na stronie drugiego modułu.

@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. moduł:

Ponownie wykorzystuje „Ważny komunikat”, importując 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
źródło
2

Pamiętaj, że aby utworzyć tak zwany „moduł funkcji”, musisz go zaimportować CommonModule. Twój kod inicjalizacji modułu będzie wyglądał następująco:

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

Więcej informacji dostępnych tutaj: https://angular.io/guide/ngmodule#create-the-feature-module

Bez przerwy
źródło
0

Czegokolwiek chcesz użyć z innego modułu, po prostu umieść go w tablicy eksportu . Lubię to-

 @NgModule({
  declarations: [TaskCardComponent],
  exports: [TaskCardComponent],
  imports: [MdCardModule]
})
Abhishek Chandel
źródło
0

Jednym wielkim i doskonałym podejściem jest załadowanie modułu z NgModuleFactory, możesz załadować moduł do innego modułu, wywołując to:

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

Mam to stąd .

Gaspar
źródło
NgModuleFactoryLoader jest teraz przestarzały, więc jaki jest najlepszy alternatywny sposób na zrobienie tego?
Muzaffar Mahmood
-2

ROZWIĄZANE JAK KORZYSTAĆ Z KOMPONENTU ZADEKLAROWANEGO W MODULE W INNYM MODUŁU.

Na podstawie wyjaśnienia Royi Namir (dziękuję bardzo). Brakuje części do ponownego użycia komponentu zadeklarowanego w module w dowolnym innym module, gdy używane jest opóźnione ładowanie.

1. Wyeksportuj komponent do modułu, który go zawiera:

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

2-ga: W module, w którym chcesz użyć 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{}

W ten sposób drugi moduł importuje pierwszy moduł, który importuje i eksportuje komponent.

Kiedy importujemy moduł do drugiego modułu, musimy go ponownie wyeksportować. Teraz możemy użyć pierwszego komponentu w drugim module.

christianAV
źródło