Я загружаю некоторые компоненты удаленно, используя следующий абстрактный код в основном приложении:
async loadRemoteModule() {
const remoteModule = this.sysplexesService.getRemoteModule();
// These library are already present, so no need to reload them.
SystemJS.set('@angular/core', SystemJS.newModule(AngularCore));
SystemJS.set('@angular/common', SystemJS.newModule(AngularCommon));
SystemJS.set('@angular/material', SystemJS.newModule(AngularMaterial));
SystemJS.set('@angular/material/snack-bar', SystemJS.newModule(AngularMaterialSnackbar));
SystemJS.set('@angular/router', SystemJS.newModule(AngularRouter));
SystemJS.set('d3', SystemJS.newModule(await import('d3')));
SystemJS.set('@angular/common/http', SystemJS.newModule(HttpClientModule));
SystemJS.set('moment', SystemJS.newModule(await import('moment')));
SystemJS.set('@angular/flex-layout', SystemJS.newModule(FlexLayoutModule));
SystemJS.set('@angular/platform-browser/animations', SystemJS.newModule(NoopAnimationsModule));
SystemJS.set('@angular/forms', SystemJS.newModule(FormsModule));
SystemJS.set('rxjs', SystemJS.newModule(rxjs));
SystemJS.set('pi-common-lib', SystemJS.newModule(piCommonLib));
SystemJS.set('@angular/animations', SystemJS.newModule(AngularAnimation));
SystemJS.import(remoteModule.url).then((module) => {
this.compiler.compileModuleAndAllComponentsAsync(module[`${remoteModule.name}Module`])
.then((moduleFactory) => {
const moduleRef = moduleFactory.ngModuleFactory.create(this.injector);
let factory = moduleFactory.componentFactories.find(
item => item.componentType.name === `${remoteModule.name}Component`);
if (factory) {
const component = this.vc.createComponent(factory);
const instance = component.instance;
}
});
}
Следующие компоненты являются частью библиотеки Angular, которая загружается предыдущей подпрограммой:
В одном из компонентов библиотеки используется закусочная материала Angular: ssc.component.ts
notify(message: string, className: string) {
this.snackBar.openFromComponent(ErrorComponent, {
data: message, verticalPosition: 'top', panelClass: className,
// data: message, verticalPosition: 'top', duration: 20000, 3: className,
});
}
, а вот пользовательская закусочная ErrorComponent:
import { Component, Inject } from '@angular/core';
import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar';
@Component({
selector: 'izoa-error',
templateUrl: './error.component.html',
styleUrls: ['./error.component.scss'],
providers: [{ provide: MatSnackBarRef, useValue: {} }, {
provide: MAT_SNACK_BAR_DATA, useValue: {}
}]
})
export class ErrorComponent {
constructor(public snackBarRef: MatSnackBarRef<ErrorComponent>, @Inject(MAT_SNACK_BAR_DATA) public data: any) { }
}
модуль:
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import {
MatFormFieldModule, MatAutocompleteModule, MatBadgeModule, MatBottomSheetModule,
MatButtonModule, MatButtonToggleModule, MatCardModule, MatCheckboxModule,
MatChipsModule, MatDatepickerModule, MatDialogModule, MatDividerModule,
MatExpansionModule, MatGridListModule, MatIconModule, MatInputModule,
MatListModule, MatMenuModule, MatNativeDateModule, MatPaginatorModule,
MatProgressBarModule, MatProgressSpinnerModule, MatRadioModule, MatRippleModule,
MatSelectModule, MatSidenavModule, MatSliderModule, MatSlideToggleModule,
MatSortModule, MatStepperModule, MatTableModule,
MatTabsModule, MatToolbarModule, MatTooltipModule, MatTreeModule
} from '@angular/material';
import { MatSnackBarRef, MAT_SNACK_BAR_DATA } from '@angular/material/snack-bar';
import {MatSnackBarModule} from '@angular/material/snack-bar';
...
import { ErrorComponent } from './ssc/error.component';
@NgModule({
declarations: [
...
ErrorComponent
],
entryComponents: [ErrorComponent],
providers: [{ provide: MatSnackBarRef, useValue: {} }, {
provide: MAT_SNACK_BAR_DATA,
useValue: {} // Add any data you wish to test if it is passed/used correctly
}],
imports: [
...
MatSnackBarModule, ...
],
exports: [
Db2SscLibComponent
]
})
export class Db2SscLibModule { }
при загрузке динамического компонента я получаю следующую ошибку:
core.js:15714 ERROR Error: No component factory found for ErrorComponent. Did you add it to @NgModule.entryComponents?
at noComponentFactoryError (core.js:9875)
at CodegenComponentFactoryResolver.resolveComponentFactory (core.js:9913)
at CdkPortalOutlet.attachComponentPortal (portal.es5.js:654)
at MatSnackBarContainer.attachComponentPortal (snack-bar.es5.js:392)
at MatSnackBar._attach (snack-bar.es5.js:856)
at MatSnackBar.openFromComponent (snack-bar.es5.js:695)
at SscComponent.notify (ssc.component.ts:330)
at SafeSubscriber.eval [as _next] (ssc.component.ts:200)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:196)
at SafeSubscriber.next (Subscriber.js:134)
errorComponent присутствует в качестве entryComponent.
entryComponents: [ErrorComponent],
Если вместо этого я использую базовую снэк-панель, так что errorComponent не нужен / загружен.
this.snackBar.open('We are sorry, but something went wrong. Please contact your administrator', 'Close', {
duration: 20000,
panelClass: className,
verticalPosition: 'top',
data: message
});
модуль загружается динамически, а снэк-бар отображается успешно.
Если я запускаю библиотеку автономно, она отлично работает с openFromComponent
this.snackBar.openFromComponent(ErrorComponent, {
data: message, verticalPosition: 'top', panelClass: className,
// data: message, verticalPosition: 'top', duration: 20000, 3: className,
});
Только когда я пытаюсь загрузить его динамически с помощью compiler.compileModuleAndAllComponentsAsync, я получаю предыдущую ошибку.
Любые указатели будутс благодарностью.