0

我编写了一个 Angular 9 模态对话框组件,我正在从 bootstrap 迁移到 ng-bootstrap 6.1。这是模板:

<ng-template #confirm let-modal tabindex="-1" aria-labelledby="confirmModalTitle">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" [innerHTML]="safeHeader"></h5>
        <button type="button" (click)="onCancel()" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body" [innerHTML]="safeBody">
      </div>
      <div class="modal-footer d-flex justify-content-between">
        <button type="button" (click)="onCancel()" class="btn btn-primary" data-dismiss="modal">No</button>
        <button type="button" (click)="onOK()" class="btn btn-secondary btn-danger">Yes</button>
      </div>
    </div>
  </div>
</ng-template>

这是代码:

import { Component, OnInit, Input, EventEmitter, Output, ViewChild, ElementRef, TemplateRef} from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { IqBaseComponent } from '../shared/iq-base.component';
import { ResponsiveState } from 'ngx-responsive';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { Template } from '@angular/compiler/src/render3/r3_ast';

declare var $: any;

@Component({
  selector: 'my-confirm',
  templateUrl: './confirm.component.html'
})
export class ConfirmComponent extends IqBaseComponent  implements OnInit {

  @Input() header: string;
  @Input() body: string;
  @Output() confirmationResult: EventEmitter<boolean> = new EventEmitter<boolean>();
  @ViewChild('confirm', { static: false }) private confirm: TemplateRef<any>;

  get safeHeader(): SafeHtml {
    return this.domSanitizer.bypassSecurityTrustHtml(this.header);
  }
  get safeBody(): SafeHtml {
    return this.domSanitizer.bypassSecurityTrustHtml(this.body);
  }
  constructor(private modalService: NgbModal, private domSanitizer: DomSanitizer, private responsiveState: ResponsiveState) {
    super(responsiveState);
  }

  ngOnInit() {
  }

  show() {
    this.modalService.open(confirm, { backdrop: true, size: 'sm', keyboard: true, centered: true });
  }

  onOK() {
    this.modalService.dismissAll();
    this.confirmationResult.emit(true);
  }

  onCancel() {
    this.modalService.dismissAll();
    this.confirmationResult.emit(false);
  }

}

show()调用并调用该方法时this.modalService.open(...),我得到以下运行时异常:

core.js:6189 ERROR Error: Uncaught (in promise): Error: ASSERTION ERROR: Type passed in is not ComponentType, it does not have 'ɵcmp' property.
Error: ASSERTION ERROR: Type passed in is not ComponentType, it does not have 'ɵcmp' property.
    at throwError (core.js:1335) [angular]
    at assertComponentType (core.js:2934) [angular]
    at ComponentFactoryResolver$1.resolveComponentFactory (core.js:33795) [angular]
    at NgbModalStack._createFromComponent (ng-bootstrap.js:6196) [angular]
    at NgbModalStack._getContentRef (ng-bootstrap.js:6178) [angular]
    at NgbModalStack.open (ng-bootstrap.js:6118) [angular]
    at NgbModal.open (ng-bootstrap.js:6290) [angular]
    at ConfirmComponent.show (confirm.component.ts:46) [angular]

该组件在另一个组件中实例化,如下所示:

<my-confirm #saveDiscard [header]="'Confirm Discarding Changes'" [body]="'Are you sure you want to discard changes?'"></my-confirm>

并在代码隐藏中引用,如下所示:

@ViewChild('saveDiscard', { static: true }) public saveDiscardConfirmer: ConfirmComponent;
...
canDeactivate(): Observable<boolean> {
    let retValue: Observable<boolean>;
    if (this.myForm.isDirty) {
      retValue = this.saveDiscardConfirmer.confirmationResult.asObservable();
      this.saveDiscardConfirmer.show();
    } else {
      retValue = of(true);
    }
    return retValue;
  }

有想法该怎么解决这个吗?

4

2 回答 2

0

为了完成这项工作,我最终得到了一个 NgbActiveModal - NgbModal 组合组件:

import { Component, OnInit, Input, EventEmitter, Output, ViewChild, ElementRef, TemplateRef} from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { IqBaseComponent } from '../shared/my-base.component';
import { ResponsiveState } from 'ngx-responsive';
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'my-confirm-content',
  templateUrl: './confirm.component.html'
})

export class ConfirmContentComponent {
  @Input() header: string;
  @Input() body: string;

  get safeHeader(): SafeHtml {
    return this.domSanitizer.bypassSecurityTrustHtml(this.header);
  }
  get safeBody(): SafeHtml {
    return this.domSanitizer.bypassSecurityTrustHtml(this.body);
  }

  constructor(public activeModal: NgbActiveModal, private domSanitizer: DomSanitizer) { }

}

@Component({
  selector: 'my-confirm',
  template: ''
})
export class ConfirmComponent extends IqBaseComponent  implements OnInit {

  @Input() header: string;
  @Input() body: string;
  @Output() confirmationResult: EventEmitter<boolean> = new EventEmitter<boolean>();
  @ViewChild('confirm', { static: false }) private confirm: TemplateRef<any>;

  constructor(private modalService: NgbModal, private responsiveState: ResponsiveState) {
    super(responsiveState);
  }

  ngOnInit() {
  }

  async show() {
    const modalRef = this.modalService.open(ConfirmContentComponent, { backdrop: true, keyboard: true });
    modalRef.componentInstance.header = this.header;
    modalRef.componentInstance.body = this.body;
    this.confirmationResult.emit(await modalRef.result);
  }

}

其中./confirm.component.html包含:

  <div class="modal-header">
    <h5 class="modal-title" [innerHTML]="safeHeader"></h5>
    <button type="button" (click)="activeModal.close(false)" class="close" aria-label="Close">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body" [innerHTML]="safeBody">
  </div>
  <div class="modal-footer d-flex justify-content-between">
    <button type="button" (click)="activeModal.close(false)" class="btn btn-primary">No</button>
    <button type="button" (click)="activeModal.close(true)" class="btn btn-secondary btn-danger">Yes</button>
  </div>

我的 app.module.ts 包括:

  entryComponents: [
    ConfirmContentComponent
  ],
于 2020-04-23T22:41:54.290 回答
0

用 ng-template 包装你的组件,如下所示:

<ng-template #myContent>
    <my-dialog-component></my-dialog-component>
</ng-template>
于 2021-07-12T22:43:45.530 回答