在 bootstrap 模态中动态加载 angular 组件
Load angular component dynamically in bootstrap modal
我正在尝试在我的应用程序中制作一个可重复使用的 quickView
模态,以使用 ng-bootstrap modal library
动态加载任何组件
就我加载文档中显示的相同示例组件而言,它工作正常,但不适用于我创建的用于测试的组件。
如何使用 quickView
模式创建动态组件以加载到 modal-body
?
https://stackblitz.com/edit/angular-quickview
我正在使用简单的 if/else 在基于名称 string
的模式中打开一个组件。
<button class="btn btn-lg btn-outline-secondary mr-2" (click)="open('default')">Launch default</button>
<button class="btn btn-lg btn-outline-danger mr-2" (click)="open('red')">Launch red</button>
<button class="btn btn-lg btn-outline-primary" (click)="open('blue')">Launch blue</button>
open(name: string) {
if (name === "default") {
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = "Default";
} else if (name === "red") {
const modalRef = this.modalService.open(RedComponent);
modalRef.componentInstance.name = "Red";
} else if (name === "blue") {
const modalRef = this.modalService.open(BlueComponent);
modalRef.componentInstance.name = "Blue";
}
}
我还尝试使用 componentFactoryResolver 将我的组件注入 modal-body
,但这也会引发错误 Error: Cannot read property 'viewContainerRef' of undefined
<div class="modal-body">
<ng-template quickView></ng-template>
</div>
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
RedComponent
);
const viewContainerRef = this.quickView.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent<any>(
componentFactory
);
componentRef.instance.name = "Red";
您可以通过在应用模块的 entryComponents 中声明这些组件,以模态动态注入组件,如下所示。
@NgModule({
declarations: [
AppComponent,
RedComponent,
BlueComponent
],
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
],
providers: [],
entryComponents: [RedComponent, BlueComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
您可以尝试添加模态服务,以便它可以解析 ComponentFactory 自定义组件,在这种情况下,模态将是单例的。
modal.service.ts
import { Injectable, ComponentFactoryResolver } from "@angular/core";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
@Injectable()
export class ModalService {
constructor(
private ngbModal: NgbModal,
private componentFactoryResolver: ComponentFactoryResolver
) {}
showDefaultModalComponent(theComponent: any, name: any) {
const componenetFactory = this.componentFactoryResolver.resolveComponentFactory(
theComponent
);
const modalRef = this.ngbModal.open(theComponent);
modalRef.componentInstance.name = name;
return modalRef;
}
showFeaturedDialog(theComponent: any, name: any) {
const componenetFactory = this.componentFactoryResolver.resolveComponentFactory(
theComponent
);
const modalRef = this.ngbModal.open(theComponent);
modalRef.componentInstance.name = name;
return modalRef;
}
}
然后将该服务注入主组件。
export class NgbdModalComponent {
constructor(private customModal: ModalService) {}
open(name: string) {
if (name === "default") {
this.customModal.showDefaultModalComponent(NgbdModalContent, "Default");
} else if (name === "red") {
this.customModal.showFeaturedDialog(RedComponent, "Red");
} else if (name === "blue") {
this.customModal.showFeaturedDialog(BlueComponent, "Blue");
}
}
}
如果您想使用 quickView 指令,请检查您的示例不工作的原因是在 RedComponent 和 BlueComponent 中。 您已经添加了两次 @Component 装饰器,如下例所示:
请查看经过编辑和工作的 Stackblitz 示例:
https://stackblitz.com/edit/angular-quickview-ykwz4i?file=src/app/modal-component.ts
注意:Angular11 中的条目组件已折旧。
我正在尝试在我的应用程序中制作一个可重复使用的 quickView
模态,以使用 ng-bootstrap modal library
就我加载文档中显示的相同示例组件而言,它工作正常,但不适用于我创建的用于测试的组件。
如何使用 quickView
模式创建动态组件以加载到 modal-body
?
https://stackblitz.com/edit/angular-quickview
我正在使用简单的 if/else 在基于名称 string
的模式中打开一个组件。
<button class="btn btn-lg btn-outline-secondary mr-2" (click)="open('default')">Launch default</button>
<button class="btn btn-lg btn-outline-danger mr-2" (click)="open('red')">Launch red</button>
<button class="btn btn-lg btn-outline-primary" (click)="open('blue')">Launch blue</button>
open(name: string) {
if (name === "default") {
const modalRef = this.modalService.open(NgbdModalContent);
modalRef.componentInstance.name = "Default";
} else if (name === "red") {
const modalRef = this.modalService.open(RedComponent);
modalRef.componentInstance.name = "Red";
} else if (name === "blue") {
const modalRef = this.modalService.open(BlueComponent);
modalRef.componentInstance.name = "Blue";
}
}
我还尝试使用 componentFactoryResolver 将我的组件注入 modal-body
,但这也会引发错误 Error: Cannot read property 'viewContainerRef' of undefined
<div class="modal-body">
<ng-template quickView></ng-template>
</div>
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
RedComponent
);
const viewContainerRef = this.quickView.viewContainerRef;
viewContainerRef.clear();
const componentRef = viewContainerRef.createComponent<any>(
componentFactory
);
componentRef.instance.name = "Red";
您可以通过在应用模块的 entryComponents 中声明这些组件,以模态动态注入组件,如下所示。
@NgModule({
declarations: [
AppComponent,
RedComponent,
BlueComponent
],
imports: [
BrowserModule,
FormsModule,
BrowserAnimationsModule,
],
providers: [],
entryComponents: [RedComponent, BlueComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
您可以尝试添加模态服务,以便它可以解析 ComponentFactory 自定义组件,在这种情况下,模态将是单例的。
modal.service.ts
import { Injectable, ComponentFactoryResolver } from "@angular/core";
import { NgbModal } from "@ng-bootstrap/ng-bootstrap";
@Injectable()
export class ModalService {
constructor(
private ngbModal: NgbModal,
private componentFactoryResolver: ComponentFactoryResolver
) {}
showDefaultModalComponent(theComponent: any, name: any) {
const componenetFactory = this.componentFactoryResolver.resolveComponentFactory(
theComponent
);
const modalRef = this.ngbModal.open(theComponent);
modalRef.componentInstance.name = name;
return modalRef;
}
showFeaturedDialog(theComponent: any, name: any) {
const componenetFactory = this.componentFactoryResolver.resolveComponentFactory(
theComponent
);
const modalRef = this.ngbModal.open(theComponent);
modalRef.componentInstance.name = name;
return modalRef;
}
}
然后将该服务注入主组件。
export class NgbdModalComponent {
constructor(private customModal: ModalService) {}
open(name: string) {
if (name === "default") {
this.customModal.showDefaultModalComponent(NgbdModalContent, "Default");
} else if (name === "red") {
this.customModal.showFeaturedDialog(RedComponent, "Red");
} else if (name === "blue") {
this.customModal.showFeaturedDialog(BlueComponent, "Blue");
}
}
}
如果您想使用 quickView 指令,请检查您的示例不工作的原因是在 RedComponent 和 BlueComponent 中。 您已经添加了两次 @Component 装饰器,如下例所示:
请查看经过编辑和工作的 Stackblitz 示例:
https://stackblitz.com/edit/angular-quickview-ykwz4i?file=src/app/modal-component.ts
注意:Angular11 中的条目组件已折旧。