在 Angular 8 中有一个可重用的模态组件

Have a reusable modal component in Angular 8

我正在使用 Angular 8 和 ng-boostrap 5.2.2。 我想要一个可重用的模态组件:

  1. 在模式中单击图像时将其关闭,然后return我将图像的值

  2. 能够从 parent 组件调用打开模式函数,我可以在我想要的元素上执行 (onclick)

我可以从 child 组件而不是 parent 组件执行此操作。

到目前为止我做了什么:

champion-modal-component.html (child)

<ng-template #mymodal let-modal>
    <div class="modal-header">
        <h4 class="modal-title" id="modal-basic-title">Bootstrap Modal</h4>
        <button type="button" class="close" aria-label="Close" (click)="modal.close('Cross click')">
            <span aria-hidden="true">×</span>
        </button>
    </div>

    <div class="modal-body">
        <div class="selected">
            <img (click)="getSelectedChampion('aatrox')" class="selected-image" src="../../../../../assets/champions/aatrox.png" alt="aatrox" title="aatrox">
            <img (click)="getSelectedChampion('ahri')" class="selected-image" src="../../../../../assets/champions/ahri.png" alt="ahri" title="ahri">
            <img (click)="getSelectedChampion('akali')" class="selected-image" src="../../../../../assets/champions/akali.png" alt="akali" title="akali">
        </div>
    </div>

    <div class="modal-footer">
        <button type="button" class="btn btn-dark" (click)="modal.close('Close click')">
            Close
        </button>
    </div>
</ng-template>

<button class="btn btn-lg btn-primary" (click)="open(mymodal)">
    Open My Modal
</button>

champion-modal-component.ts (child)

import { Component, OnInit, Input } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-champion-modal',
  templateUrl: './champion-modal.component.html',
  styleUrls: ['./champion-modal.component.scss']
})
export class ChampionModalComponent implements OnInit {

  championSelected = '';

  constructor(private modalService: NgbModal) { }

  ngOnInit() {
  }

  open(content: any) {
    this.modalService.open(content, { ariaLabelledBy: 'modal-basic-title' });
  }

  getSelectedChampion(champion: string) {
    console.log('champion: ', champion);
    this.modalService.dismissAll();
    this.championSelected = champion;
  }

}

champion-suggestion-component.html (parent)

<!-- I WOULD LIKE THIS and not use a button in the child -->
 <img (click)="openModal()" class="suggestion-image"
                src="../../../../../assets/champions/aatrox.png" alt="aatrox" title="aatrox">    

<app-champion-modal></app-champion-modal>

这是否可以通过模态服务或 EventEmitter 实现?

您可能正在寻找的是 @Output()

使用它时,您应该能够在关闭 child.

组件时 return 一个值或在 parent 组件上调用一个方法

Child:

// ts
@Output() close = new EventEmitter<any>();

// html
<div (click)="close.emit(value)"></div>

Parent:

// html
<child-el (close)="functiontoCall($event)"></child-el>

// ts
functiontoCall(event: any) {
  console.log(event);
  this.closeChild(); // hypthetical function to close the child
}

您可以将此代码调整为 return 单击图像时的图像值。 在您的情况下,child 是图像组件,parent 是这些图像的容器。

我终于用服务做到了:

champion-modal.component.html (child)

<div class="modal-header">
    <h4 class="modal-title">Select a Champion</h4>
    <button type="button" class="close" aria-label="Close" (click)="activeModal.close('Cross click')">
        <span aria-hidden="true">×</span>
    </button>
</div>

<div class="modal-body" id="modal-body">
    <div class="search-container">
    <div class="image-container">
        <div *ngFor="let image of championImages" class="medium-name-circle">
            <img (click)="getSelectedChampion(image.value)" class="medium-name-image"
                src="../../../../../assets/champions/{{image.value}}.png" alt="{{image.value}}"
                title="{{image.viewValue}}">
            <div class="text">{{image.viewValue}}</div>
        </div>
    </div>
</div>

champion-modal.component.ts (child)

constructor(public activeModal: NgbActiveModal, private modalService: ChampionModalService) { }

  ngOnInit() {
  }

  getSelectedChampion(champion: string) {
    this.activeModal.close();
    this.championSelected = champion;
    this.modalService.getSelectedChampion(this.championSelected);
  }

champion-modal.service.ts

import { Injectable } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { ChampionModalComponent } from './champion-modal.component';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class ChampionModalService {

  // Observable string sources
  private componentMethodCallSource = new Subject<any>();

  // Observable string streams
  componentMethodCalled$ = this.componentMethodCallSource.asObservable();

  roleSelected = '';
  teamSelected = '';

  constructor(private modal: NgbModal) { }

  open() {
    this.modal.open(ChampionModalComponent, { size: 'lg' });
  }

  getSelectedChampion(champion: string) {
    this.componentMethodCallSource.next({
      championName: champion,
      role: this.roleSelected,
      team: this.teamSelected
    });
  }
}

champion-suggestion.component.html (parent)

<img (click)="openModal(role, 'yourTeam')" class="suggestion-image"
                src="../../../../../assets/champions/aatrox.png" alt="aatrox" title="aatrox">

champion-suggestion.component.ts (parent)

constructor(private modalService: ChampionModalService) {
    // Callback of the modal
    this.modalService.componentMethodCalled$.subscribe(
      (parameters) => {
        this.setSelectedChampion(parameters.role, parameters.championName, parameters.team);
      }
    );
  }

  ngOnInit() {
  }

  setSelectedChampion(role: string, champion: string, team: string) {
    if (team === 'yourTeam') {
      this.yourTeamRole[role] = champion;
    }
    if (team === 'enemyTeam') {
      this.enemyTeamRole[role] = champion;
    }
  }

  openModal(role: string, team: string) {
    this.modalService.roleSelected = role;
    this.modalService.teamSelected = team;
    this.modalService.open();
  }

我有 Circular dependency detected 警告,我可以避免吗?