Angular 9 нг- bootstrap 6.1 Не работает метод открытия модального компонента - PullRequest
0 голосов
/ 24 апреля 2020

Я написал модальный диалоговый компонент 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;
  }

Любые идеи о том, как это исправить?

1 Ответ

0 голосов
/ 24 апреля 2020

Чтобы сделать эту работу, я получил комбо-компонент 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. тс включает в себя:

  entryComponents: [
    ConfirmContentComponent
  ],
...