如何在Angular中从一个组件打开另一个组件的模态框?

6

我创建了一个模态框组件,并在modal.component.html文件中编写了我的模态框代码。我想在头部组件(header component)的header.component.html文件中使用这个模态框。

以下是与此相关的头部组件(header component)的一部分:

<div style="text-align: center">
  <a class="social-account-profile icon-plus"
     (click)="onButtonClick()"</a>
</div>

onButtonClick 是我在 header.component.ts 中的一个方法,如下:

export class HeaderComponent implements OnInit {

  constructor(public router: Router, public authService: AuthService,
              public appGlobal: AppGlobals, public  modal: ModalComponent) {
  }

  ngOnInit() {
  }

  onButtonClick() {
    this.modal.openModal();
  }

} 

openModal是我在modal.component.ts文件中的以下方法:

export class ModalComponent implements OnInit {

  @ViewChild('projctModal') projctModal: any;
  openModal() {
    this.projctModal.show();
  }

  constructor(private formvalidation: FormValidation) {
  }

  ngOnInit() {
  }

}

我的modal.component.html文件如下:

<div mdbModal #projctModal="mdbModal" class="modal fade top " id="projctModal" tabindex="-1" role="dialog"
     aria-labelledby="myModalLabel"
     aria-hidden="true">
</div>
当我运行代码时,我的Chrome控制台会显示以下错误信息:
ERROR TypeError: Cannot read property 'show' of undefined
我该如何修复这个问题?

看起来你正在直接注入你的组件。你是想从头开始构建一个模态框吗?如果是这样,那么你缺少一些关键项或者你没有在这里展示它们。 - ed-tester
不,我使用MDBootstrap模态框。如果我直接在组件的HTML文件中使用模态框,它可以工作,但我想要一个特定的组件,将所有我的模态框代码放在其中,并从其他HTML组件中调用每个模态框,只要我需要。 - Mohandes
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
13

您需要创建一个模态服务才能使下面的示例正常工作。

ModalComponent

import { Component, ElementRef, Input, OnInit,ViewChild, OnDestroy } from '@angular/core';
import {ModalService} from './modal.service';

@Component({
  selector: 'app-modal',
  templateUrl: './modal.component.html'
})
export class ModalComponent implements OnInit, OnDestroy {
  @Input() id: string;
    private element: any;
     @ViewChild('basicModal') basicModal: ElementRef;


    constructor(private modalService: ModalService, private el: ElementRef) {
        this.element = el.nativeElement;
    }

    ngOnInit(): void {
        let modal = this;

        // ensure id attribute exists
        if (!this.id) {
            console.error('modal must have an id');
            return;
        }
        // add self (this modal instance) to the modal service so it's accessible from controllers
        this.modalService.add(this);
    }

    // remove self from modal service when directive is destroyed
    ngOnDestroy(): void {
        this.modalService.remove(this.id);
        this.element.remove();
    }

    // open modal
    open(): void {
        this.basicModal.show();
    }

    // close modal
    close(): void {
        this.basicModal.hide()
    }


}

而且这是HTML

<div mdbModal #basicModal="mdbModal" class="modal fade right" tabindex="-1" role="dialog" aria-labelledby="myBasicModalLabel"
  aria-hidden="true">
  <div class="modal-dialog modal-full-height modal-right" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title w-100" id="myModalLabel">Modal title</h4>

        <button type="button" class="close pull-right" aria-label="Close" (click)="basicModal.hide()">
          <span aria-hidden="true">×</span>
        </button>
       </div>
      <div class="modal-body">
         <ng-content></ng-content>
      </div>
      <div class="modal-footer">
        <button type="button" mdbBtn color="secondary" class="waves-light" aria-label="Close" (click)="basicModal.hide()" mdbWavesEffect>Close</button>
        <button type="button" mdbBtn color="primary" class="relative waves-light" mdbWavesEffect>Save!</button>
      </div>
    </div>
  </div>
</div>

以下是模态服务代码

import { Injectable } from '@angular/core';

@Injectable()
export class ModalService {

  private modals: any[] = [];

     add(modal: any) {
        this.modals.push(modal);
    }

    remove(id: string) {
        this.modals = this.modals.filter(x => x.id !== id);
    }

    open(id: string) {
        let modal: any = this.modals.filter(x => x.id === id)[0];
        modal.open();
    }

    close(id: string) {
        let modal: any = this.modals.filter(x => x.id === id)[0];
        modal.close();
    }

}

在你的实际组件中这样使用它:

import { Component } from '@angular/core';

import {ModalService} from './modal/modal.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
   private bodyText: string;

    constructor(private modalService: ModalService) {
    }

    ngOnInit() {
        this.bodyText = 'This text can be updated in modal 1';
    }

    openModal(id: string) {
        this.modalService.open(id);
    }

    closeModal(id: string) {
        this.modalService.close(id);
    }


}

并且它的HTML代码

<div class="col-md-6 col-md-offset-3">
    <h1>Home</h1>
    <p>{{bodyText}}</p>
    <button (click)="openModal('custom-modal-1')">Open Modal 1</button>
    <button (click)="openModal('custom-modal-2')">Open Modal 2</button>

</div>


<app-modal id="custom-modal-1">
    <h1>A Custom Modal!</h1>
    <p>Home page text: <input type="text" [(ngModel)]="bodyText" /></p>
    <button (click)="closeModal('custom-modal-1');">Close</button>
</app-modal>

<app-modal id="custom-modal-2">
    <h1>A Custom Modal!</h1>

</app-modal>

2

首先,在您的父组件中...

import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
constructor(){
  ...
  private modalService: NgbModal,
  ...
}
创建一个函数,并在按钮点击时调用它。
  callModal() {
    const modalRef = this.modalService.open(ComponentName,
      { size: 'xl', backdrop: 'static', keyboard: false, windowClass:'my-modal' 
      });
  }

在编程中,有一个重要的事实,就是必须在父组件中导入你的模态框组件。

这是解决这个问题最简单的方法...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,