48

Usually we use data-target="#myModal" in the <button> to open a modal. 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. 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. 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?

<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>
2
  • why to use [hidden] in the modal ? Commented Feb 15, 2016 at 5:01
  • @PardeepJain As I said, [hidden] and class="modal fade" together the modal will never show even [hidden]="false". If u want to use [hidden], u need remove class="modal fade" Commented Feb 15, 2016 at 5:30

16 Answers 16

62

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.

4
  • 19
    This does not work at compile time and not with typescript. Its sort of hackish Commented Aug 19, 2016 at 0:43
  • The link http://valor-software.com/ng2-bootstrap/#/modals results in a 404 today...
    – gogognome
    Commented Jan 1, 2018 at 21:23
  • @gogognome thanks, I just removed that link, because nowadays there are many packages available if the person choose to use a package. Commented Jan 1, 2018 at 23:47
  • 1
    Thank you alot. Coolest solution. I don't use 3rd party bootstrap in angular. I just copy links from official site. I don't like too much of code jungle and i open popup only after data is loaded from backend.This is exactly what i was looking for. Commented May 21, 2019 at 8:42
34

Include jQuery as usual inside script tags in index.html.

After all the imports but before declaring @Component, add:

declare var $: any;

Now you are free to use jQuery anywhere in your Angular 2 TypeScript code:

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

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

4
  • 2
    I do it this way. Bootstrap 3 depends somewhat on jquery.
    – yonexbat
    Commented Aug 24, 2017 at 18:21
  • 4
    The best answer without installing a third party package. jQuery should be installed when using Bootstrap, so might as well use it in the controller and this way is also in the Bootstrap docs. Thanks Commented Nov 24, 2018 at 16:04
  • Don't forget link or install bootstrap.js Commented Jul 21, 2022 at 18:22
  • jQuery shouldn't be used wtih Angular 2+
    – sagar1025
    Commented Sep 9, 2022 at 13:44
13

Easy way to achieve this in angular 2 or 4 (Assuming that you are using bootstrap 4)

Component.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

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';
}
4
  • 1
    Could you please specify where in your solution you assumed usage of Bootstrap 4 instead of 3? I am using version 3 and this worked for me anyway, so I think I missed some detail and would like to learn more :)
    – MaxAxeHax
    Commented Mar 20, 2018 at 16:29
  • @MaxAxeHax I use word "Assuming using bootstarp 4", Just in case previous or upcoming version of bootstrap class for hide and show is change then you just need to replace that class in openModel and closeModel function. Commented Apr 9, 2018 at 6:49
  • 5
    Doesn't work for me. Neither the snippet nor code based on it.
    – Tomasz O.
    Commented Oct 10, 2018 at 12:56
  • Doesn't work. Neither the snippet nor code based on i Commented Jul 18, 2021 at 10:04
12

The below answer is in reference to the latest ng-bootstrap

Install

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

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

<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>
1
  • 1
    Very nice! I didn't note TemplateRef<any>; // Note: TemplateRef but it was important. Thanks, Arjun Commented Jun 21, 2020 at 5:36
7

Best way I have found. Put #lgModal or some other variable name in your modal.

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();
  }

}
5

Here is my full implementation of modal bootstrap angular2 component:

I assume that in your main index.html file (with <html> and <body> tags) at the bottom of <body> tag you have:

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

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:

<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:

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:

<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.

7
  • could you please take a look at this stackblitz.com/edit/angular-xesgxe I want to show a modal when input is clicked. But the compiler can't find this.el.modal or this.el.nativeElement.modal() Commented Aug 11, 2018 at 8:20
  • got it working using $().modal. It is in one of the answers below Commented Aug 11, 2018 at 8:33
  • In method ngAfterViewInit and methods open/close I in fact use it. However in this answer goal was to provide working "modal" component (with example usage) - however it was 2 years ago so may be now it is outdated. Commented Aug 11, 2018 at 9:14
  • Yes, I see it now. I am concerned about mixing jquery and angular code but this one is the only one I could get working. If you happen to find a soln. which is more Angular, please do update. So would I. Commented Aug 11, 2018 at 9:20
  • Could you please help me understand why this line is important declare var $: any;. I expected that because I have already included jquery in my project, I should be able to use $ anywhere. Also, your comment that becouse this override jQuery which was changed by bootstrap. Does Bootstrap's come with its own implementation of JQuery? Commented Aug 12, 2018 at 7:51
5

I do not feel there is anything wrong with using JQuery with angular and bootstrap, since it is included when adding bootstrap.

  1. Add the $ right after the imports like this


import {.......

declare var $: any;

@component.....
  1. modal should have an id like this

<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
0
4

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).

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. In component ts file, import ViewChild from @angular/core and write below code:

@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

this.myHiddenBtn.nativeElement.click();
2
  • Worked for me. Thanks! Commented Nov 21, 2019 at 4:01
  • Nice solution! Even if not the Angular way :) Commented Nov 3, 2020 at 7:03
2

Think I found the correct way to do it using 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:

@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):

...
<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.

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.

0

The Way i used to do it without lots of coding is.. I have the hidden button with the id="employeeRegistered"

On my .ts file I import ElementRef from '@angular/core'

Then after I process everything on my (click) method do as follow:

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

then the modal displays as expected..

0

For me I had to settimeout in addition to @arjun-sk solution's (link), as I was getting the error

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

I am using a variable to control show and hide and rely on the button the open the modal

ts code:

showModel(){
  this.showModal = true;
}

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>

0

We can use jquery to open bootstrap modal.

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

@ng-bootstrap/ng-bootstrap npm I m using for this as in the project bootstrap is used, for material, we used dialog

HTML Code

  <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

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

constructor(
    private modalService: NgbModal
  ) { }

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

Simply, npm install --save @types/bootstrap try to match typing version with your bootstrap version. E.g. you have Bootstrap 4.3.1 then npm install --save @types/[email protected]

0

Let me explain the solution. Bit tricky ....... Parent HTML File ........

<!-- 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

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

<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

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');
        }
        }

Not the answer you're looking for? Browse other questions tagged or ask your own question.