使用多个bootstrap模态(ngx-bootstrap和Angular)时出现问题

时间:2017-09-22 09:08:23

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

我在Angular 4中使用多个bootstrap模式时遇到了问题。也许你可以帮我解决这个问题。只需一个模态,代码工作正常。我无法使用第一个加载模式的按钮/形式。第二个工作正常。打开和关闭第二个模态后,第一个模态也起作用......奇怪。有什么不对?



<!-- 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>
&#13;
&#13;
&#13;

&#13;
&#13;
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) {


  }
&#13;
&#13;
&#13;

谢谢你们的时间!

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

因此,经过一些修复,生产使用和测试之后,我可以说我找到了解决嵌套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
  });

功能:

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

希望这对某人<3有帮助。