web-dev-qa-db-fra.com

Comment utiliser le code pour ouvrir un modal dans Angular 2?

Habituellement, nous utilisons data-target="#myModal" dans <button> pour ouvrir un modal. À l'heure actuelle, j'ai besoin de codes d'utilisation pour contrôler quand ouvrir le modal.

Si j'utilise [hidden] ou *ngIf pour l'afficher, j'ai besoin de supprimer class="modal fade", sinon le modal ne s'affichera jamais. Comme ça:

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

Toutefois, dans ce cas, après avoir supprimé class="modal fade", le modal ne s’ajoutera pas et n’aura pas d’ombre en arrière-plan. Et ce qui est pire, il apparaîtra au bas de l'écran au lieu du centre de l'écran.

Existe-t-il un moyen de conserver class="modal fade" et d'utiliser du code pour l'ouvrir? 

<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>
21
Hongbo Miao

C'est une façon que j'ai trouvée. Vous pouvez ajouter un bouton caché:

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

Puis utilisez le code pour "cliquer" sur le bouton pour ouvrir le modal:

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

De cette façon, vous pouvez conserver le style de démarrage du modal et l'animation en fondu.

32
Hongbo Miao

Incluez jQuery comme d'habitude dans les balises de script dans index.html.

Après toutes les importations mais avant de déclarer @Component, ajoutez:

declare var $: any;

Maintenant, vous êtes libre d’utiliser jQuery n’importe où dans votre code Angular 2 TypeScript:

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

Référence: https://stackoverflow.com/a/38246116/2473022

16
Moobie

Un moyen facile d'y parvenir dans angular 2 ou 4 (En supposant que vous utilisez bootstrap 4 )

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

Composant.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';
}
8
Umang Patwa

Voici ma mise en œuvre complète du composant modal bootstrap angular2:

Je suppose que dans votre fichier index.html principal (avec les balises <html> et <body>) au bas de la balise <body>, vous avez:

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

Et exemple d'utilisation dans le composant client de l'éditeur: Client-edit-composant.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 et mfoot ar paramètres facultatifs.

6
Kamil Kiełczewski

Le meilleur moyen que j'ai trouvé. Mettez #lgModal ou un autre nom de variable dans votre modal.

A votre avis:

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

Dans votre composant

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
Judson Terrell

La réponse ci-dessous fait référence au dernier ng-bootstrap

Installer 

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 { }

Contrôleur de composants

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

}

HTML du composant

<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>
2
Arjun SK

Je pense avoir trouvé la bonne façon de le faire en utilisant ngx-bootstrap . Première importation des classes suivantes:

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

Dans l'implémentation de classe de votre composant, ajoutez une propriété @ViewCild, une fonction pour ouvrir le modal et n'oubliez pas de configurer modalService comme une propriété privée dans le constructeur de la classe de composants:

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

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

La partie 'editSomething' de la déclaration @ViewChild fait référence au fichier de modèle de composant et à son implémentation de modèle modal ( #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>

Et enfin, appelez la méthode pour ouvrir le modal où vous voulez comme ceci:

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

this.editSomethingModal est un TemplateRef qui pourrait être affiché par ModalService.

Et voilà! Le modal défini dans votre fichier de modèle de composant est indiqué par un appel provenant de votre implémentation de classe de composant. Dans mon cas, je l'ai utilisé pour montrer un modal à l'intérieur d'un gestionnaire d'événements.

1
Torsten Barthel

Pour moi, je devais régler en plus de la solution @ arjun-sk ( link ), car je recevais le error

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