【问题标题】:Trouble using multiple bootstrap modals (ngx-bootstrap and Angular)使用多个引导模式(ngx-bootstrap 和 Angular)时遇到问题
【发布时间】:2018-03-03 19:26:27
【问题描述】:

在 Angular 4 中使用多个引导模式确实有问题。也许你可以帮我解决这个问题。该代码仅使用一种模式就可以正常工作。我无法使用第一个加载模式的按钮/表单。第二个工作正常。打开和关闭第二个模态后,第一个模态也起作用了……奇怪。有什么不对?

<!-- ADD MODAL-->
<div bsModal #addModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myAddModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Add Dimension</h4>
        <button type="button" class="close" (click)="addModal.hide()" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <form>
          <div class="form-group">
            <label for="formGroupInput">TAG</label>
            <input type="text" class="form-control" id="formGroupExampleInput" placeholder="Example input" aria-describedby="keyHelp"
              value="" disabled>
            <small id="keyHelp" class="form-text text-muted">Notice that this field is a surrogate key!</small>
          </div>
          <div class="form-group">
            <label for="formGroupInput2">Name</label>
            <input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input" value="">
          </div>
          <div class="form-group">
            <label for="formGroupInput3">Description</label>
            <input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input" value="">
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" id="dfsdfsdfsdf" class="btn btn-secondary" (click)="addModal.hide()">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

<!-- EDIT MODAL-->
<div bsModal #editModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">Edit {{currentItem?.NAME}}</h4>
        <button type="button" class="close" (click)="editModal.hide()" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <form>
          <div class="form-group">
            <label for="formGroupInput">TAG</label>
            <input type="text" class="form-control" id="formGroupExampleInput" placeholder="Example input" aria-describedby="keyHelp"
              value="{{currentItem?.TAG}}" disabled>
            <small id="keyHelp" class="form-text text-muted">You'll need to delete this entry to change this key value!</small>
          </div>
          <div class="form-group">
            <label for="formGroupInput2">Name</label>
            <input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input" value="{{currentItem?.NAME}}">
          </div>
          <div class="form-group">
            <label for="formGroupInput3">Description</label>
            <input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input" value="{{currentItem?.COMM}}">
          </div>
        </form>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="editModal.hide()">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

import { Component, OnInit, ViewChild } from '@angular/core';
import { DataService } from "../data.service";
import { ModalDirective } from 'ngx-bootstrap/modal/modal.component';

@Component({

  templateUrl: './dimensions.component.html',
  styleUrls: ['./dimensions.component.scss']
})
export class DimensionsComponent implements OnInit {

  @ViewChild('editModal') public editModal: ModalDirective;
  @ViewChild('addModal') public addModal: ModalDirective;
  currentItem;

  openModal(item: any) {
    this.currentItem = item;
    this.editModal.show();

  }


  openAddModal() {
    this.addModal.show();

  }


  //Attributes
  public currentVar;
  subscription;
  dimensionData;
  rows;

  constructor(private _dataService: DataService) {


  }

谢谢你们的时间!

更新:通过在代码中切换模式序列也会出现问题,但只是在另一个模式方面。

【问题讨论】:

    标签: javascript twitter-bootstrap angular modal-dialog ngx-bootstrap


    【解决方案1】:

    bsModal 指令不太适合嵌套模式,请转换为使用 bsModal 服务,请参见此处的示例: https://valor-software.com/ngx-bootstrap/#/modals#service-nested

    【讨论】:

      【解决方案2】:

      因此,经过一些修复、生产使用和测试,我可以说我找到了解决嵌套 ngx-bootstrap 模态问题的方法。我为BsModalService 编写了一个服务包装器。

      modalIndexing = {};
      hasInited = false;
      
      constructor(
          router: Router,
          private modalService: BsModalService,
      ) {
          router.events
              .pipe(filter((event: NavigationEvent) => (event instanceof NavigationStart)))
              .subscribe(() => this.terminateAll());
      }
      
      // Just a modal dude
      resolveModal(component, position: 'center' | 'static' = 'center', initialState?: any): void {
          const config: ModalOptions = {
              class: modalClassDict[position] + ' ss-modal',
              initialState
          };
      
          // For nested launches, wait until previous hide to open new
          setTimeout(() => {
              this.modalService.show(component, config);
          }, initialState.hasTimeout ? 600 : 0);
      }
      
      // Modal dude that will return something 
      // if you want to of cause, no pressure
      resolveModalSub(component, position: 'center' | 'static' = 'center', initialState?: any): Observable<any> {
          const config: ModalOptions = {
              class: modalClassDict[position] + ' ss-modal',
              initialState
          };
      
          const bsModalRef = this.modalService.show(component, config);
          bsModalRef.content.onClose = new Subject<any>();
      
          const modalSub = bsModalRef.content.onClose.pipe(take(1));
          this.healthCheck(modalSub);
      
          return modalSub;
      }
      
      // This sneaky little bastard will return something if it hides!
      resolveModalSubCheckHide(component, position: 'center' | 'static' = 'center', initialState?: any): Observable<any> {
          const config: ModalOptions = {
              class: modalClassDict[position] + ' ss-modal',
              initialState
          };
      
          const bsModalRef = this.modalService.show(component, config);
          bsModalRef.content.onClose = new Subject<any>();
      
          const modalSub = bsModalRef.content.onClose.pipe(take(1));
          this.healthCheck(modalSub, true);
      
          return modalSub;
      }
      
      // This thingy does some pseudo-indexing and cleans up the mess you left
      private healthCheck(modalSub, needToCheckHide = false) {
      
          // The only property ngx-bootstrap modal service
          // is able to return is the number of openned modals
          // so we are heading out from it 
          const index = this.modalService.getModalsCount();
      
          this.modalIndexing[index] = {
              modalSub,
              needToCheckHide
          };
      
          // First modal initiates onHide sub 
          if (!this.hasInited) {
              this.hasInited = true;
      
              this.modalService.onHide
                  .subscribe(() => {
                      if (_.keys(this.modalIndexing).length) {
                          // This event emits after the modal is closed so its a +1
                          const indexedSub = this.modalIndexing[this.modalService.getModalsCount() + 1];
      
                          // Handeles the case when you need to know if modal was closed
                          if (indexedSub.needToCheckHide) {
                              indexedSub.modalSub.next(false);
                          }
      
                          // Completes sub of a value return and cleans itself from dictionary
                          if (indexedSub.modalSub) {
                              indexedSub.modalSub.complete();
                          }
                          delete this.modalIndexing[this.modalService.getModalsCount() + 1];
                      }
                  });
          }
      }
      
      // Termiantes all modal windows in user navigates via back / forward
      private terminateAll() {
          _.keys(this.modalIndexing).forEach(index => this.modalService.hide(index));
      }
      

      基本用法:

      const data = {
        // your initial data
      };
      
      this.dialogService.resolveModalSubCheckHide(YourModalComponentToDisplay, 'center', data)
        .subscribe((value) => {
            // processing
        });
      

      特点:

      • 作为主题的返回值处理
      • 性能友好
      • 不留下任何未完成的科目
      • 如果隐藏可以返回值
      • 处理无限的嵌套级别
      • 可以排队以启动模式
      • 手动导航时自动关闭

      希望这对某人有帮助

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-11
        • 2023-03-06
        • 2019-05-16
        • 1970-01-01
        • 2019-09-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多