【问题标题】:Have a reusable modal component in Angular 8在 Angular 8 中有一个可重用的模态组件
【发布时间】:2020-07-17 17:16:23
【问题描述】:

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

  1. 当点击模态中的图像时,关闭它并返回图像的值

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

我可以从子组件而不是父组件执行此操作。

到目前为止我做了什么:

champion-modal-component.html(孩子)

<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(孩子)

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(父)

<!-- 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 是否可行?

【问题讨论】:

    标签: angular modal-dialog ng-bootstrap


    【解决方案1】:

    我终于通过服务做到了:

    champion-modal.component.html(孩子)

    <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(孩子)

    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(父母)

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

    champion-suggestion.component.ts(父母)

    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 警告,我可以避免吗?

    【讨论】:

      【解决方案2】:

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

      在使用这个时,你应该能够在关闭子组件时返回一个值或调用父组件上的方法。

      孩子:

      // ts
      @Output() close = new EventEmitter<any>();
      
      // html
      <div (click)="close.emit(value)"></div>
      
      

      家长:

      // html
      <child-el (close)="functiontoCall($event)"></child-el>
      
      // ts
      functiontoCall(event: any) {
        console.log(event);
        this.closeChild(); // hypthetical function to close the child
      }
      

      您可以修改此代码以在单击图像时返回图像的值。 在您的情况下,子组件是图像组件,父组件是这些图像的容器。

      【讨论】:

        猜你喜欢
        • 2019-12-08
        • 1970-01-01
        • 2021-03-28
        • 2020-02-17
        • 1970-01-01
        • 2018-05-18
        • 1970-01-01
        • 2023-02-10
        • 2018-11-30
        相关资源
        最近更新 更多