angular - Kako otvoriti komponentu iz modula koji se učitava na zahtjev u NgbModal?


Suočavam se s problemom prilikom pokušaja učitavanja dinamičke komponente iz modul učitanog na zahtjev. Preciznije, pokušavam otvoriti komponentu za prijavu u modalnom prozoru (https://ng-bootstrap.github.io/#/components/modal/examples) umjesto na zasebnoj stranici, dok istovremeno želim zadržati zasebnu rutu/stranicu za prijavu netaknutom.

Sada, jedna opcija mi se čini da moram eager učitati login komponentu u app modulu, što nije ništa drugo nego privremeni trik. Dakle, ne želim ovo rješenje.

Pokušao sam izravno koristiti komponentu, ali kao što sam i očekivao, pojavila mi se sljedeća pogreška:

Nije pronađena tvornička komponenta za SigninComponent. Jeste li je dodali u @NgModule.entryComponents?

Pretražio sam i pronašao ovaj link: https://github.com/angular/angular/issues/14324, ali ne mogu ga natjerati da radi.

Iznenađen sam što nisam mogao pronaći odgovarajuće rješenje za ovaj problem jer se radi o vrlo čestom slučaju. Bilo kakva pomoć ili prijedlozi su cijenjeni. Hvala!

Odgovor #1

Komponente koje se ne koriste izravno u predlošcima putem svog selektora moraju se dodati u entryComponents niz modula u @NgModule dekoratoru. Kada otvarate modal u Bootstrapu, zapravo ne koristite selektor komponente nigdje, pa je vaš SignInComponent jedan takav primjer.

Ti bi učinio nešto ovako

@NgModule({
    //...
    declarations: [
        SignInComponent,
    ],
    entryComponents: [
        SignInComponent,
    ]
})
export class LazyLoadedModule {
}

označiti komponentu za kompilaciju iako nije referencirana u predlošku nijedne druge komponente putem svog selektora.

Više o ulaznim komponentama, kako one rade i zašto ih trebate deklarirati na ovaj način možete pročitati u službenoj Angular dokumentaciji ovdje. Kao i u ovom StackOverflow postu.

Odgovor #2

Evo kako sam uspio učiniti ono što ti želiš. Ideja je da, budući da je login komponenta u ljepljivom modulu, budući da ljepljivi moduli se učitavaju pomoću rutera prilikom navigacije na neke rute, potrebno je navigirati unutar modala na rutu koja učitava ljepljivi modul i prikazuje login komponentu. I to se može učiniti pomoću imenovanog router outlet-a. Nisam baš iskusan s imenovanim router outlet-ima, pa možda postoji nekoliko stvari za doraditi, ali čini se da radi.

Dakle, pretpostavljajući da imate lijeni modul LoginModule s rutom praznog puta koja prikazuje komponentu za prijavu, evo kako se mogu definirati rute glavnog modula:

export const ROUTES: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'login', 
    loadChildren: './login/login.module#LoginModule'
  },
  { 
    path: 'modal-login',
    component: ModalLoginShellComponent, 
    outlet: 'modal', 
    children: [
       {
         path: '',
         loadChildren: './login/login.module#LoginModule'
       }
    ]
  }
];

Komponenta početne stranice imala bi poveznicu koja omogućuje otvaranje ModalLoginComponent unutar modala (kao što je prikazano u ng-bootstrap primjeru). Predložak ove ModalLoginComponent izgledao bi ovako:

<div class="modal-header">
  <h4 class="modal-title">Hi there!</h4>
  <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
<div class="modal-body">
  <router-outlet name="modal"></router-outlet>
</div>
<div class="modal-footer">
  <button type="button" class="btn btn-outline-dark" (click)="activeModal.close('Close click')">Close</button>
</div>

Važan dio je

<router-outlet name="modal"></router-outlet>

Omogućuje, unutar modalnog prozora, navigaciju do rute, i posebno, do rute koja bi učitala lijeno učitani modul.

Kod ModalLoginComponent-a imao bi sljedeći ngOnInit(), koji bi pokrenuo navigaciju:

ngOnInit() {
  this.router.navigate([{outlets: {'modal': ['modal-login']}}]);
}

Ovo bi tako učitalo ModalLoginShellComponent i njegovu zadanu, na zahtjev učitanu dječju rutu unutar tijela modala. ModalLoginShellComponent je glupa komponenta koja ništa ne radi, i samo ima, kao svoj predložak

<router-outlet></router-outlet>

Povezani članci