How to use code to open a modal in Angular 2?

169,687

Solution 1

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.

Solution 2

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

Solution 3

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

Solution 4

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>

Solution 5

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

}
Share:
169,687
Hongbo Miao
Author by

Hongbo Miao

https://www.hongbomiao.com

Updated on July 09, 2022

Comments

  • Hongbo Miao
    Hongbo Miao almost 2 years

    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>
    
  • Judson Terrell
    Judson Terrell almost 8 years
    This does not work at compile time and not with typescript. Its sort of hackish
  • yonexbat
    yonexbat almost 7 years
    I do it this way. Bootstrap 3 depends somewhat on jquery.
  • gogognome
    gogognome over 6 years
    The link http://valor-software.com/ng2-bootstrap/#/modals results in a 404 today...
  • Hongbo Miao
    Hongbo Miao over 6 years
    @gogognome thanks, I just removed that link, because nowadays there are many packages available if the person choose to use a package.
  • MaxAxeHax
    MaxAxeHax over 6 years
    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 :)
  • Umang Patwa
    Umang Patwa about 6 years
    @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.
  • Manu Chadha
    Manu Chadha almost 6 years
    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()
  • Manu Chadha
    Manu Chadha almost 6 years
    got it working using $().modal. It is in one of the answers below
  • Kamil Kiełczewski
    Kamil Kiełczewski almost 6 years
    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.
  • Manu Chadha
    Manu Chadha almost 6 years
    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.
  • Manu Chadha
    Manu Chadha almost 6 years
    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?
  • Manu Chadha
    Manu Chadha almost 6 years
    I suppose I found the answer. By doing declare var $:any, we declare a variable that exists somewhere in the JS - found it from some other question in SO
  • Kamil Kiełczewski
    Kamil Kiełczewski almost 6 years
    @ManuChadha I ask more general similar question: stackoverflow.com/questions/50516233/…
  • Tomasz O.
    Tomasz O. over 5 years
    Doesn't work for me. Neither the snippet nor code based on it.
  • deanwilliammills
    deanwilliammills over 5 years
    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
  • Nabin Kumar Khatiwada
    Nabin Kumar Khatiwada about 5 years
    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.
  • Aspiring Dev
    Aspiring Dev over 4 years
    Worked for me. Thanks!
  • Hamid Hoseini
    Hamid Hoseini about 4 years
    Very nice! I didn't note TemplateRef<any>; // Note: TemplateRef but it was important. Thanks, Arjun
  • Torsten Barthel
    Torsten Barthel over 3 years
    Nice solution! Even if not the Angular way :)
  • Fatih Doğan
    Fatih Doğan almost 3 years
    Doesn't work. Neither the snippet nor code based on i