简体   繁体   English

如何使用代码在 Angular 2 中打开模态?

[英]How to use code to open a modal in Angular 2?

Usually we use data-target="#myModal" in the <button> to open a modal.通常我们在<button>中使用data-target="#myModal"来打开一个模式。 Right now I need use codes to control when to open the modal.现在我需要使用代码来控制何时打开模式。

If I use [hidden] or *ngIf to show it, I need remove class="modal fade" , otherwise, the modal will never show.如果我使用[hidden]*ngIf来显示它,我需要删除class="modal fade" ,否则,模态将永远不会显示。 Like this:像这样:

<div [hidden]="hideModal" id="myModal">

However, in this case, after removing class="modal fade" , the modal won't fade in and has no shade in the background.但是,在这种情况下,删除class="modal fade"后,模态框不会淡入并且在背景中没有阴影。 And what's worse, it will show at the screen bottom instead of screen center.更糟糕的是,它会显示在屏幕底部而不是屏幕中心。

Is there a way to keep class="modal fade" and use code to open it?有没有办法保持class="modal fade"并使用代码打开它?

<button type="button" data-toggle="modal" data-target="#myModal">Open Modal</button>

<div id="myModal" class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <p>Some text in the modal.</p>
      </div>
    </div>
  </div>
</div>

This is one way I found.这是我找到的一种方法。 You can add a hidden button:您可以添加一个隐藏按钮:

<button id="openModalButton" [hidden]="true" data-toggle="modal" data-target="#myModal">Open Modal</button>

Then use the code to "click" the button to open the modal:然后使用代码“单击”按钮打开模态:

document.getElementById("openModalButton").click();

This way can keep the bootstrap style of the modal and the fade in animation.这种方式可以保持模态和淡入动画的引导样式。

Include jQuery as usual inside script tags in index.html.像往常一样在 index.html 的脚本标签中包含 jQuery。

After all the imports but before declaring @Component, add:在所有导入之后但在声明 @Component 之前,添加:

declare var $: any;

Now you are free to use jQuery anywhere in your Angular 2 TypeScript code:现在,您可以在 Angular 2 TypeScript 代码中的任何位置自由使用 jQuery:

$("#myModal").modal('show');

Reference: https://stackoverflow.com/a/38246116/2473022参考: https : //stackoverflow.com/a/38246116/2473022

Easy way to achieve this in angular 2 or 4 (Assuming that you are using bootstrap 4 )angular 2 或 4 中实现此目的的简单方法(假设您使用的是bootstrap 4

Component.html组件.html

 <button type="button" (click)="openModel()">Open Modal</button> <div #myModel class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title ">Title</h5> <button type="button" class="close" (click)="closeModel()"> <span aria-hidden="true">&times;</span> </button> </div> <div class="modal-body"> <p>Some text in the modal.</p> </div> </div> </div> </div>

Component.ts组件.ts

import {Component, OnInit, ViewChild} from '@angular/core';

@ViewChild('myModal') myModal;

openModel() {
  this.myModal.nativeElement.className = 'modal fade show';
}
closeModel() {
   this.myModal.nativeElement.className = 'modal hide';
}

The below answer is in reference to the latest ng-bootstrap以下答案参考了最新的ng-bootstrap

Install安装

npm install --save @ng-bootstrap/ng-bootstrap

app.module.ts app.module.ts

import {NgbModule} from '@ng-bootstrap/ng-bootstrap';

@NgModule({
  declarations: [
    ...
  ],
  imports: [
    ...

    NgbModule

  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Component Controller组件控制器

import { TemplateRef, ViewChild } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-app-registration',
  templateUrl: './app-registration.component.html',
  styleUrls: ['./app-registration.component.css']
})

export class AppRegistrationComponent implements OnInit {

  @ViewChild('editModal') editModal : TemplateRef<any>; // Note: TemplateRef

  constructor(private modalService: NgbModal) { }

  openModal(){
    this.modalService.open(this.editModal);
  }

}

Component HTML组件 HTML

<ng-template #editModal let-modal>

<div class="modal-header">
  <h4 class="modal-title" id="modal-basic-title">Edit Form</h4>
  <button type="button" class="close" aria-label="Close" (click)="modal.dismiss()">
    <span aria-hidden="true">&times;</span>
  </button>
</div>

<div class="modal-body">
  
  <form>
    <div class="form-group">
      <label for="dateOfBirth">Date of birth</label>
      <div class="input-group">
        <input id="dateOfBirth" class="form-control" placeholder="yyyy-mm-dd" name="dp" ngbDatepicker #dp="ngbDatepicker">
        <div class="input-group-append">
          <button class="btn btn-outline-secondary calendar" (click)="dp.toggle()" type="button"></button>
        </div>
      </div>
    </div>
  </form>

</div>

<div class="modal-footer">
  <button type="button" class="btn btn-outline-dark" (click)="modal.close()">Save</button>
</div>

</ng-template>

Best way I have found.我找到的最好的方法。 Put #lgModal or some other variable name in your modal.#lgModal或其他一些变量名放入您的模式中。

In your view:在您看来:

<div bsModal #lgModal="bs-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-lg">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" (click)="lgModal.hide()" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
        <h4 class="modal-title">Large modal</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
    </div>
  </div>
</div>

In your component在您的组件中

import {Component, ViewChild, AfterViewInit} from '@angular/core';
import {CORE_DIRECTIVES} from '@angular/common';
// todo: change to ng2-bootstrap
import {MODAL_DIRECTIVES, BS_VIEW_PROVIDERS} from 'ng2-bootstrap/ng2-bootstrap';
import {ModalDirective} from 'ng2-bootstrap/ng2-bootstrap';


@Component({
  selector: 'modal-demo',
  directives: [MODAL_DIRECTIVES, CORE_DIRECTIVES],
  viewProviders:[BS_VIEW_PROVIDERS],
  templateUrl: '/app/components/modals/modalDemo.component.html'
})
export class ModalDemoComponent implements AfterViewInit{

  @ViewChild('childModal') public childModal: ModalDirective;
  @ViewChild('lgModal') public lgModal: ModalDirective;

  public showChildModal():void {
    this.childModal.show();
  }

  public hideChildModal():void {
    this.childModal.hide();
  }

  ngAfterViewInit() {
      this.lgModal.show();
  }

}

Here is my full implementation of modal bootstrap angular2 component:这是我对 modal bootstrap angular2 组件的完整实现:

I assume that in your main index.html file (with <html> and <body> tags) at the bottom of <body> tag you have:我认为在你的主index.html文件(用<html><body>标签),在底部<body>标签必须:

  <script src="assets/js/jquery-2.1.1.js"></script>
  <script src="assets/js/bootstrap.min.js"></script>

modal.component.ts: modal.component.ts:

import { Component, Input, Output, ElementRef, EventEmitter, AfterViewInit } from '@angular/core';

declare var $: any;// this is very importnant (to work this line: this.modalEl.modal('show')) - don't do this (becouse this owerride jQuery which was changed by bootstrap, included in main html-body template): let $ = require('../../../../../node_modules/jquery/dist/jquery.min.js');

@Component({
  selector: 'modal',
  templateUrl: './modal.html',
})
export class Modal implements AfterViewInit {

    @Input() title:string;
    @Input() showClose:boolean = true;
    @Output() onClose: EventEmitter<any> = new EventEmitter();

    modalEl = null;
    id: string = uniqueId('modal_');

    constructor(private _rootNode: ElementRef) {}

    open() {
        this.modalEl.modal('show');
    }

    close() {
        this.modalEl.modal('hide');
    }

    closeInternal() { // close modal when click on times button in up-right corner
        this.onClose.next(null); // emit event
        this.close();
    }

    ngAfterViewInit() {
        this.modalEl = $(this._rootNode.nativeElement).find('div.modal');
    }

    has(selector) {
        return $(this._rootNode.nativeElement).find(selector).length;
    }
}

let modal_id: number = 0;
export function uniqueId(prefix: string): string {
    return prefix + ++modal_id;
}

modal.html:模态.html:

<div class="modal inmodal fade" id="{{modal_id}}" tabindex="-1" role="dialog"  aria-hidden="true" #thisModal>
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header" [ngClass]="{'hide': !(has('mhead') || title) }">
                <button *ngIf="showClose" type="button" class="close" (click)="closeInternal()"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
                <ng-content select="mhead"></ng-content>
                <h4 *ngIf='title' class="modal-title">{{ title }}</h4>
            </div>
            <div class="modal-body">
                <ng-content></ng-content>
            </div>

            <div class="modal-footer" [ngClass]="{'hide': !has('mfoot') }" >
                <ng-content select="mfoot"></ng-content>
            </div>
        </div>
    </div>
</div>

And example of usage in client Editor component: client-edit-component.ts:以及在客户端编辑器组件中的使用示例:client-edit-component.ts:

import { Component } from '@angular/core';
import { ClientService } from './client.service';
import { Modal } from '../common';

@Component({
  selector: 'client-edit',
  directives: [ Modal ],
  templateUrl: './client-edit.html',
  providers: [ ClientService ]
})
export class ClientEdit {

    _modal = null;

    constructor(private _ClientService: ClientService) {}

    bindModal(modal) {this._modal=modal;}

    open(client) {
        this._modal.open();
        console.log({client});
    }

    close() {
        this._modal.close();
    }

}

client-edit.html:客户端-edit.html:

<modal [title]='"Some standard title"' [showClose]='true' (onClose)="close()" #editModal>{{ bindModal(editModal) }}
    <mhead>Som non-standart title</mhead>
    Some contents
    <mfoot><button calss='btn' (click)="close()">Close</button></mfoot>
</modal>

Ofcourse title, showClose, mhead and mfoot ar optional parameters.当然title、showClose、mhead和mfoot都是可选参数。

I'm currently using Bootstrap 4.3 in Angular 8 and want to open modal window programmatically (without actually clicking on some button as the official demo shows).我目前正在 Angular 8 中使用 Bootstrap 4.3,并希望以编程方式打开模态窗口(而不是像官方演示所示那样实际点击某个按钮)。

Following method works for me: The general idea is to create a button associated to a modal window.以下方法对我有用:一般的想法是创建一个与模态窗口关联的按钮。 First make sure after you click this button, it can open the modal.首先确定你点击这个按钮后,它可以打开模态。 Then give this button tag an id using hashtag, for example #hiddenBtn .然后使用 hashtag 给这个按钮标签一个 id,例如#hiddenBtn In component ts file, import ViewChild from @angular/core and write below code:在组件 ts 文件中, import ViewChild from @angular/core并编写以下代码:

@ViewChild('hiddenBtn', {static: false}) myHiddenBtn;

After that, whenever you want to open this modal window in your component ts code, write following code to simulate click operation之后,每当你想在你的组件ts代码中打开这个模态窗口时,编写以下代码来模拟点击操作

this.myHiddenBtn.nativeElement.click();

I do not feel there is anything wrong with using JQuery with angular and bootstrap, since it is included when adding bootstrap.我不觉得将 JQuery 与 angular 和 bootstrap 一起使用有什么问题,因为在添加 bootstrap 时包含了它。

  1. Add the $ right after the imports like this像这样在导入后立即添加 $


import {.......

declare var $: any;

@component.....
  1. modal should have an id like this模态应该有一个这样的id

<div id="errorModal" class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" ..............

  1. then have a method like this然后有一个这样的方法

showErrorModal() { $("#errorModal").modal('show'); }

  1. call the method on a button click or anywhere you wish单击按钮或您希望的任何地方调用该方法

Think I found the correct way to do it using ngx-bootstrap .认为我找到了使用ngx-bootstrap的正确方法。 First import following classes:首先导入以下类:

import { ViewChild } from '@angular/core';
import { BsModalService, ModalDirective } from 'ngx-bootstrap/modal';
import { BsModalRef } from 'ngx-bootstrap/modal/bs-modal-ref.service';

Inside the class implementation of your component add a @ViewCild property, a function to open the modal and do not forget to setup modalService as a private property inside the components class constructor:在组件的类实现中添加一个 @ViewCild 属性,一个打开模态的函数,不要忘记在组件类构造函数中将 modalService 设置为私有属性:

@ViewChild('editSomething') editSomethingModal : TemplateRef<any>;
...

modalRef: BsModalRef;
openModal(template: TemplateRef<any>) {
  this.modalRef = this.modalService.show(template);
}
...
constructor(
private modalService: BsModalService) { }

The 'editSomething' part of the @ViewChild declaration refers to the component template file and its modal template implementation ( #editSomething ): @ViewChild 声明的“editSomething”部分指的是组件模板文件及其模态模板实现( #editSomething ):

...
<ng-template #editSomething>
  <div class="modal-header">
  <h4 class="modal-title pull-left">Edit ...</h4>
  <button type="button" class="close pull-right" aria-label="Close" 
   (click)="modalRef.hide()">
    <span aria-hidden="true">&times;</span>
  </button>
  </div>

  <div class="modal-body">
    ...
  </div>


  <div class="modal-footer">
    <button type="button" class="btn btn-default"
        (click)="modalRef.hide()"
        >Close</button>
  </div>
</ng-template>

And finaly call the method to open the modal wherever you want like so:最后调用该方法在任何你想要的地方打开模态:

console.log(this.editSomethingModal);
this.openModal( this.editSomethingModal );

this.editSomethingModal is a TemplateRef that could be shown by the ModalService. this.editSomethingModal是TemplateRef可能由ModalService显示。

Et voila!等等! The modal defined in your component template file is shown by a call from inside your component class implementation.组件模板文件中定义的模态由组件类实现内部的调用显示。 In my case I used this to show a modal from inside an event handler.就我而言,我用它来显示事件处理程序内部的模式。

The Way i used to do it without lots of coding is.. I have the hidden button with the id="employeeRegistered"我过去在没有大量编码的情况下这样做的方式是..我有一个带有id="employeeRegistered"的隐藏按钮

On my .ts file I import ElementRef from '@angular/core'在我的.ts文件中,我import ElementRef from '@angular/core'

Then after I process everything on my (click) method do as follow:然后在我处理完我的(click)方法上的所有内容后, (click)执行以下操作:

this.el.nativeElement.querySelector('#employeeRegistered').click();

then the modal displays as expected..然后模态按预期显示..

For me I had to settimeout in addition to @arjun-sk solution's ( link ), as I was getting the error对我来说,除了@arjun-sk 解决方案( 链接)之外,我还必须设置超时,因为我收到了错误

setTimeout(() => {
      this.modalService.open(this.loginModal, { centered: true })
    }, 100); 

I am using a variable to control show and hide and rely on the button the open the modal我正在使用一个变量来控制显示和隐藏,并依靠按钮打开模态

ts code: ts 代码:

showModel(){
  this.showModal = true;
}

html: html:

<button type="button" data-toggle="modal" data-target="#myModal" (click)="showModel()>Open Modal</button>

<div *ngIf="showModal" >
  <div id="myModal" class="modal fade">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-body">
                <p>Some text in the modal.</p>
            </div>
        </div>
    </div>
</div>

We can use jquery to open bootstrap modal.我们可以使用 jquery 来打开 bootstrap modal。

ngAfterViewInit() { 
      $('#scanModal').modal('show'); 
}

@ng-bootstrap/ng-bootstrap npm I m using for this as in the project bootstrap is used, for material, we used dialog @ng-bootstrap/ng-bootstrap npm 我为此使用,因为在项目中使用了引导程序,对于材料,我们使用了对话框

HTML Code HTML代码

  <span (click)="openModal(modalRef)" class="form-control input-underline pl-3 ">Open Abc Modal
 </span>

Modal template模态模板

<ng-template class="custom-modal"  #modalRef let-c="close" let-d="dismiss">
   <div class="modal-header custom-modal-head"><h4 class="modal-title">List of Countries</h4>
     <button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
         <img src="assets/actor/images/close.png" alt="">
      </button>
  </div>
  <div class="modal-body country-select">
       <div class="serch-field">
           <div class="row">
               <div class="col-md-12">
                 <input type="text"  class="form-control input-underline pl-3" placeholder="Search Country"
                    [(ngModel)]="countryWorkQuery" [ngModelOptions]="{standalone: true}">
                 <ul *ngIf="countries" class="ng-star-inserted">
                   <li (click)="setSelectedCountry(cntry, 'work');d('Cross click');" class="cursor-pointer"
                   *ngFor="let cntry of countries | filterNames:countryWorkQuery ">{{cntry.name}}</li>
                 </ul>
                 <span *ngIf="!modalSpinner && (!countries || countries.length<=0)">No country found</span>
                 <span *ngIf="modalSpinner" class="loader">
                     <img src="assets/images/loader.gif" alt="loader">
                 </span>
               </div>
             </div>
       </div>
 </div>
</ng-template>

Ts File Ts文件

import {NgbModal, ModalDismissReasons} from '@ng-bootstrap/ng-bootstrap';

constructor(
    private modalService: NgbModal
  ) { }

  openModal(modalContent){
     this.modalService.open(modalContent, { centered: true});
   }

Simply, npm install --save @types/bootstrap try to match typing version with your bootstrap version.简单地说, npm install --save @types/bootstrap尝试将键入版本与您的引导程序版本相匹配。 Eg you have Bootstrap 4.3.1 then npm install --save @types/bootstrap@4.3.1例如你有 Bootstrap 4.3.1 然后npm install --save @types/bootstrap@4.3.1

Let me explain the solution.让我解释一下解决方案。 Bit tricky....... Parent HTML File........有点棘手.......父 HTML 文件.......

<!-- parent component html -->
your code....
<div class="d-flex align-items-center flex-nowrap justify-content-end">
    <button (click)="openCancelStandingOrder(line)" class="btn btn-primary mx-1" type="button">Delete</button>
</div>
<div *ngIf="isCancelStandingOrderOpen">
    <child-component [data]="data" (onCloseModel)="onCloseModal($event)"></child-component>
</div>

Parent TS File父 TS 文件

export class ParentComponent {
isCancelStandingOrderOpen: boolean = false;
data: any;
// ....
fetchData() {
// API Call
}

openCancelStandingOrder(line) {
this.isCancelStandingOrderOpen = true;
this.data = line;
}

onCloseModal(reload) {
// prevent unnessecery api calls
if (reload) {

// fetch list data again
this.fetchData();
}

// Do needful

}
}

Child HTML File孩子 HTML 文件

<ng-template #cancelStandingOrderModal let-modal>
    <div class="modal-header">
        <h4 class="modal-title" id="modal-basic-title">Title</h4>
        <button type="button" class="btn-close" aria-label="Close" (click)="onDismiss(modal)"></button>
    </div>
    <div class="modal-body">
        <!--  your content here -->
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-outline-success" (click)="onSubmit(modal)">Save</button>
        <button type="button" class="btn btn-outline-dark" (click)="onExit(modal)">Cancel</button>
    </div>
</ng-template>

Child TS File子 TS 文件

export class ChildComponent {
// ...
@Input() data: any; // Get data from parent
@Output() public onCloseModal: EventEmitter<boolean> = new EventEmitter();
    @ViewChild('cancelStandingOrderModal', { static: false }) public formModal: TemplateRef<any>; // Note: Target html
        instance

        // Using bootstrap modals: https://ng-bootstrap.github.io/#/components/modal/examples
        constructor(private modalService: NgbModal) { }

        ngOnInit() {
        // Any data manipulation
        }

        ngAfterViewInit() {
        this.openModal();
        }

        openModal() {
        this.modalService.open(this.formModal, {
        backdrop: false,
        centered: true,
        size: 'lg',
        keyboard: false, // disable ESC key to close
        });
        }

        onSubmit(modal) {
        // Do needful.. api calls etc....
        // ...
        this.closeModel(modal, true)
        }

        onExit(modal) {
        // Execute any mathod befor closing modal
        // like unsaved data alert etc.
        this.closeModel(modal, false)
        }


        onDismiss(modal) {
        this.closeModel(modal, false)
        }

        closeModel(modal: any, reload: boolean = false) {
        this.onCloseModal.emit(reload)
        modal.close('close');
        }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM