O modalitate ușoară de a face un dialog de confirmare în Angular? (Programare, Angular, Confirmare)

victor dencowski a intrebat.

Există vreo modalitate nu atât de complicată de a face un dialog de confirmare în angular 2, ideea este să faceți clic pe un element și apoi să arătați un popup sau modal pentru a confirma ștergerea acestuia, am încercat angular 2 modals de aici angular2-modal, , dar nu știu cum să fac ca dacă confirmi sau anulezi să facă ceva. funcția click funcționează bine, singura problemă este că nu știu prea bine cum să o folosesc. Mai am și un alt modal cu același plugin cu diferența că eu folosesc același plugin.

this.modal.open(MyComponent);

Și nu vreau să creez o altă componentă doar pentru a arăta o casetă de confirmare de aceea întreb.

Comentarii

  • „The easy way” ar fi să folosesc ceva de genul angular2-modal așa cum ați menționat. Altfel va trebui să vă construiți singur unul, iar asta nu aș putea numi-o o cale ușoară. Ai văzut pe linkul pe care l-ai furnizat că existau exemple plunker care arătau utilizarea 🙂 embed.plnkr.co/mbPzd8 –  > Por AJT82.
  • înțeleg, atunci va fi o idee bună să creez o componentă cu popup-ul de confirmare care să aibă 2 butoane și care atunci când este apăsat să execute o funcție în componenta principală. În exemplul el folosește keyup 5 pentru a închide dialogul trebuie să îl închid și să apelez la o funcție. Oricum, voi încerca să fac cât mai simplu și mai clar posibil și voi posta rezultatele –  > Por victor dencowski.
  • Există și alte modale acolo, care ar putea avea și alte caracteristici încorporate pe care le-ai putea dori, dar cerințele tale nu par prea dificile, așa că bănuiesc că multe ar fi potrivite pentru tine, dar dacă îți place, navighează și găsește unul care îți place. Iată câteva exemple: npmjs.com/search?q=angular+2+modal Încercați-le și reveniți la SO dacă întâmpinați probleme! Codare fericită! 🙂 –  > Por AJT82.
  • o altă situație în care angular face lucrurile mult mai complicate decât ar trebui să fie. Un alt punct pentru React –  > Por Felipe.
8 răspunsuri
Philip John

Metoda 1

O modalitate simplă de a confirma este de a folosi alerta de confirmare nativă a browserului. șablonul poate avea un buton sau un link.

<button type=button class="btn btn-primary"  (click)="clickMethod('name')">Delete me</button>

Iar metoda componentă poate fi ceva de genul de mai jos.

clickMethod(name: string) {
  if(confirm("Are you sure to delete "+name)) {
    console.log("Implement delete functionality here");
  }
}

Metoda 2

O altă modalitate de a obține un dialog de confirmare simplu este de a utiliza componentele angular bootstrap, cum ar fi ng-bootstrap sau ngx-bootstrap. Puteți pur și simplu să instalați componenta și să utilizați componenta modală.

  1. Exemple de modale care utilizează ng-bootstrap
  2. Exemple de modale care utilizează ngx-bootstrap.

Metoda 3

Furnizată mai jos este o altă modalitate de a implementa un popup de confirmare simplu folosind angular2/material pe care l-am implementat în proiectul meu.

app.module.ts

import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ConfirmationDialog } from './confirm-dialog/confirmation-dialog';

@NgModule({
  imports: [
    ...
    FormsModule,
    ReactiveFormsModule
  ],
  declarations: [
    ...
    ConfirmationDialog
  ],
  providers: [ ... ],
  bootstrap: [ AppComponent ],
  entryComponents: [ConfirmationDialog]
})
export class AppModule { }

confirmation-dialog.ts

import { Component, Input } from '@angular/core';
import { MdDialog, MdDialogRef } from '@angular/material';

@Component({
  selector: 'confirm-dialog',
  templateUrl: '/app/confirm-dialog/confirmation-dialog.html',
})
export class ConfirmationDialog {
  constructor(public dialogRef: MdDialogRef<ConfirmationDialog>) {}

  public confirmMessage:string;
}

confirmation-dialog.html

<h1 md-dialog-title>Confirm</h1>
<div md-dialog-content>{{confirmMessage}}</div>
<div md-dialog-actions>
  <button md-button style="color: #fff;background-color: #153961;" (click)="dialogRef.close(true)">Confirm</button>
  <button md-button (click)="dialogRef.close(false)">Cancel</button>
</div>

app.component.html

<button (click)="openConfirmationDialog()">Delete me</button>

app.component.ts

import { MdDialog, MdDialogRef } from '@angular/material';
import { ConfirmationDialog } from './confirm-dialog/confirmation-dialog';

@Component({
  moduleId: module.id,
  templateUrl: '/app/app.component.html',
  styleUrls: ['/app/main.css']
})

export class AppComponent implements AfterViewInit {
  dialogRef: MdDialogRef<ConfirmationDialog>;

  constructor(public dialog: MdDialog) {}

  openConfirmationDialog() {
    this.dialogRef = this.dialog.open(ConfirmationDialog, {
      disableClose: false
    });
    this.dialogRef.componentInstance.confirmMessage = "Are you sure you want to delete?"

    this.dialogRef.afterClosed().subscribe(result => {
      if(result) {
        // do confirmation actions
      }
      this.dialogRef = null;
    });
  }
}

index.html => adăugată următoarea foaie de stiluri

<link rel="stylesheet" href="node_modules/@angular/material/core/theming/prebuilt/indigo-pink.css">

Comentarii

  • De asemenea, a trebuit să import BrowserAnimationsModule din @angular/platform-browser/animations și MaterialModule din @angular/material –  > Por hestellezg.
  • De asemenea, pentru stiluri am folosit @import '[email protected]/material/prebuilt-themes/deeppurple-amber.css'; următorul acest –  > Por hestellezg.
  • înapoi un an mai târziu, am uitat să adaug un rezolvat. În prezent sunt într-un proiect mare și am optat pentru matDialog care este complet, ușor de utilizat, dar totuși puternic și vă oferă o modalitate ușoară de a comunica între componenta principală și dialogul care permite atât de multe opțiuni noi. Dacă cineva are această problemă, vă recomand să o încercați, necesită o anumită pregătire, dar merită, deoarece funcționează perfect.  > Por victor dencowski.
  • Va funcționa acest lucru cu o funcție de rechemare? Nu am încercat codul, citindu-l, văd doar un callback tipizat static, de exemplu, dacă doriți să faceți un apel dinamic, cum ar fi să ștergeți ceva după ID, ar trebui să analizați un parametru și să instalați logica acolo. –  > Por KeaganFouche.
  • +1. Acesta este un exemplu foarte bun care funcționează aproape din start. Pentru cea mai recentă versiune, trebuie doar să înlocuiți md cu mat și poate folosiți unele stiluri încorporate pentru butoane: mat-raised-button color="primary" –  > Por Alexei – verificați Codidact.
Tarek Badr

poți folosi window.confirm în interiorul funcției tale combinat cu condiția if

 delete(whatever:any){
    if(window.confirm('Are sure you want to delete this item ?')){
    //put your delete method logic here
   }
}

atunci când apelezi metoda de ștergere va apărea un mesaj de confirmare și când apeși ok se va executa toată logica din interiorul condiției if.

Comentarii

  • Nu trebuie să folosești cuvântul cheie window. –  > Por Ambrus Tóth.
tilo

Am ajuns destul de târziu la petrecere, dar iată o altă implementare care folosește : https://stackblitz.com/edit/angular-confirmation-dialog

confirmation-dialog.service.ts

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';

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

import { ConfirmationDialogComponent } from './confirmation-dialog.component';

@Injectable()
export class ConfirmationDialogService {

  constructor(private modalService: NgbModal) { }

  public confirm(
    title: string,
    message: string,
    btnOkText: string = 'OK',
    btnCancelText: string = 'Cancel',
    dialogSize: 'sm'|'lg' = 'sm'): Promise<boolean> {
    const modalRef = this.modalService.open(ConfirmationDialogComponent, { size: dialogSize });
    modalRef.componentInstance.title = title;
    modalRef.componentInstance.message = message;
    modalRef.componentInstance.btnOkText = btnOkText;
    modalRef.componentInstance.btnCancelText = btnCancelText;

    return modalRef.result;
  }

}

confirmation-dialog.component.ts

import { Component, Input, OnInit } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
  selector: 'app-confirmation-dialog',
  templateUrl: './confirmation-dialog.component.html',
  styleUrls: ['./confirmation-dialog.component.scss'],
})
export class ConfirmationDialogComponent implements OnInit {

  @Input() title: string;
  @Input() message: string;
  @Input() btnOkText: string;
  @Input() btnCancelText: string;

  constructor(private activeModal: NgbActiveModal) { }

  ngOnInit() {
  }

  public decline() {
    this.activeModal.close(false);
  }

  public accept() {
    this.activeModal.close(true);
  }

  public dismiss() {
    this.activeModal.dismiss();
  }

}

confirmation-dialog.component.html

<div class="modal-header">
  <h4 class="modal-title">{{ title }}</h4>
    <button type="button" class="close" aria-label="Close" (click)="dismiss()">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    {{ message }}
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-danger" (click)="decline()">{{ btnCancelText }}</button>
    <button type="button" class="btn btn-primary" (click)="accept()">{{ btnOkText }}</button>
  </div>

Utilizați dialogul astfel:

public openConfirmationDialog() {
    this.confirmationDialogService.confirm('Please confirm..', 'Do you really want to ... ?')
    .then((confirmed) => console.log('User confirmed:', confirmed))
    .catch(() => console.log('User dismissed the dialog (e.g., by using ESC, clicking the cross icon, or clicking outside the dialog)'));
  }

Comentarii

  • Am urmat codul de mai sus, dar atunci când fac clic pe buton, modalitatea pop up vine pentru o fracțiune de secundă & dispare imediat. Mă puteți ajuta să rezolv această problemă? –  > Por watraplion.
  • Se întâmplă acest lucru și cu demo-ul legat de StackBlitz? –  > Por tilo.
  • Nu… În StackBlitz funcționează bine. Am copiat toate aceste fișiere în șablonul meu de proiect, unde mă confrunt cu această problemă –  > Por watraplion.
  • Ei bine, acest lucru este greu (a se citi: imposibil) de depanat fără informații suplimentare. –  > Por tilo.
  • @tilo: Se pare că funcționează doar în Angular 5. Nu funcționează în Angular 4. Și, mai important, au eliminat @Injectable() în versiunile ulterioare ale ng-bootstrap –  > Por SK..
Sudeep Rane

UPDATE: Plunkr a adăugat

Am căutat o soluție pe toate forumurile, dar nu am găsit niciuna, așa că am găsit o soluție cu Old School Javascript Callback function. acesta este un mod foarte simplu și curat de a crea un dialog de confirmare și de a seta funcții Callback pentru ambele DA și NU evenimente de clic.
Am folosit Bootstrap CSS pentru Modal și Un serviciu de alertă cu rxjs Subiect.

alert.component.html

        <div *ngIf="message.type == 'confirm'"  class="modal-body">
            <div class="row">
                <div class="col-md-12">
                    <h3 class="text-center">{{message.text}}</h3>
                </div>
            </div>
            <div class="row">
                <div class="col-md-12">
                    <p class="text-center">
                        <a (click)="message.noFn()">
                            <button class="btn btn-pm">No</button>
                        </a>
                        <a (click)="message.siFn()">
                            <button  class="btn btn-sc" >Yes</button>
                        </a>
                    </p>
                </div>
            </div>
         </div>

alert.component.ts

export class AlertComponent {
    message: any;
    constructor(
      public router: Router, 
      private route: ActivatedRoute, 
      private alertService: AlertService,
   ) { }
   ngOnInit() {
    //this function waits for a message from alert service, it gets 
    //triggered when we call this from any other component
    this.alertService.getMessage().subscribe(message => {
        this.message = message;
    });
}

Cea mai importantă parte este aici alert.service.ts

     import { Injectable } from '@angular/core'; 
     import { Router, NavigationStart } from '@angular/router'; 
     import { Observable } from 'rxjs'; 
     import { Subject } from 'rxjs/Subject';
     @Injectable() export class AlertService {
          private subject = new Subject<any>();
          constructor(){}
          confirm(message: string,siFn:()=>void,noFn:()=>void){
            this.setConfirmation(message,siFn,noFn);
          }
          setConfirmation(message: string,siFn:()=>void,noFn:()=>void) {
            let that = this;
            this.subject.next({ type: "confirm",
                        text: message,
                        siFn:
                        function(){
                            that.subject.next(); //this will close the modal
                            siFn();
                        },
                        noFn:function(){
                            that.subject.next();
                            noFn();
                        }
                     });

                 }

          getMessage(): Observable<any> {
             return this.subject.asObservable();
          }
       }

Apelați funcția din orice componentă

this.alertService.confirm("You sure Bro?",function(){
    //ACTION: Do this If user says YES
},function(){
    //ACTION: Do this if user says NO
})

Plunkrhttps://embed.plnkr.co/vWBT2nWmtsXff0MXMKdd/

Comentarii

  • hi.I’m looking for something like this ..but the code above not working for me.no modal shown and no error in console.tanks –  > Por mrapi.
  • Bună ziua Mrpi, Poți să te asiguri dacă ai css-ul Bootstrap la locul lui? Acum, dacă vrei să testezi cum arată modalitatea ta, elimină ng-if și verifică. –  > Por Sudeep Rane.
  • Funcționează.mulțumesc.cum rămâne cu poziționarea pe verticală la centru? –  > Por mrapi.
  • Trebuie să efectuați un calcul JS pentru a face acest lucru pe verticală, nu se poate face doar prin CSS. Dar pentru orizontală margin: 0 auto funcționează ca un farmec! –  > Por Sudeep Rane.
  • @NasiruddinSaiyed: ați putea spune vă rog ce module să instalați. Primesc un avertisment: AVERTISMENT în ./node_modules/@ng-bootstrap/ng-bootstrap/datepicker/datepicker-i18n.js 32:39-56 „export ‘getLocaleDayNames’ nu a fost găsit în ‘@angular/common’ –  > Por SK..
Lars Rødal

Ați putea folosi sweetalert: https://sweetalert.js.org/guides/

npm install sweetalert --save

Apoi, pur și simplu importați-l în aplicația dvs:

import swal from 'sweetalert';

Dacă treceți două argumente, primul va fi titlul modalului, iar al doilea va fi textul acestuia.

swal("Here's the title!", "...and here's the text!");

Chris HG

Iată o abordare foarte diferită, folosind funcționalitatea nativă de confirmare a javascript și o directivă Angular personalizată. Este super flexibil și destul de ușor:

Utilizare:

<button (hrsAreYouSure) (then)="confirm(arg1)" (else)="cancel(arg2)">
  This will execute confirm if user presses Ok on the confirmation dialog, or cancel if they
  hit Cancel
</button>

Directiva:

import {Directive, ElementRef, EventEmitter, Inject, OnInit, Output} from '@angular/core';

@Directive({
  selector: '[hrsAreYouSure]'
})

export class AreYouSureDirective implements OnInit {

  @Output() then = new EventEmitter<boolean>();
  @Output() else = new EventEmitter<boolean>();

  constructor(@Inject(ElementRef) private element: ElementRef) { }

  ngOnInit(): void {
    const directive = this;
    this.element.nativeElement.onclick = function() {
      const result = confirm('Are you sure?');
      if (result) {
        directive.then.emit(true);
      } else {
        directive.else.emit(true);
      }
    };
  }
}

Comentarii

  • Chrome mi-a cerut să înlătur parantezele din jurul hrsAreYouSure din buton, altfel nu ar fi funcționat. –  > Por Reid.
  • De asemenea, dacă apăsați enter în timp ce caseta de dialog este afișată, o confirmați, indiferent dacă aceasta a fost sau nu intenția dumneavoastră. –  > Por Reid.
Anjana Silva

Adăugarea mai multor opțiuni la răspuns.

Ați putea folosi npm i sweetalert2

Nu uitați să adăugați stilul la răspunsul dvs. angular.json

"styles": [
         ...
          "node_modules/sweetalert2/src/sweetalert2.scss"
          ]

Apoi doar importați,

// ES6 Modules or TypeScript
import Swal from 'sweetalert2'


// CommonJS
const Swal = require('sweetalert2')

Bum, sunteți gata de plecare.

Swal.fire({
  title: 'Are you sure?',
  text: 'You will not be able to recover this imaginary file!',
  icon: 'warning',
  showCancelButton: true,
  confirmButtonText: 'Yes, delete it!',
  cancelButtonText: 'No, keep it'
}).then((result) => {
  if (result.value) {
    Swal.fire(
      'Deleted!',
      'Your imaginary file has been deleted.',
      'success'
    )
  // For more information about handling dismissals please visit
  // https://sweetalert2.github.io/#handling-dismissals
  } else if (result.dismiss === Swal.DismissReason.cancel) {
    Swal.fire(
      'Cancelled',
      'Your imaginary file is safe :)',
      'error'
    )
  }
})

Mai multe despre acest lucru:- https://www.npmjs.com/package/sweetalert2

Sper că acest lucru ajută pe cineva.

Mulțumesc.

Lars H

Pentru a reutiliza o singură implementare a dialogului de confirmare într-o aplicație cu mai multe module, dialogul trebuie să fie implementat într-un modul separat. Iată o modalitate de a face acest lucru cu Material Design și FxFlex, deși ambele pot fi reduse sau înlocuite.

Mai întâi modulul partajat (./app.module.ts):

import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MatDialogModule, MatSelectModule} from '@angular/material';
import {ConfirmationDlgComponent} from './confirmation-dlg.component';
import {FlexLayoutModule} from '@angular/flex-layout';

@NgModule({
   imports: [
      CommonModule,
      FlexLayoutModule,
      MatDialogModule
   ],
   declarations: [
      ConfirmationDlgComponent
   ],
   exports: [
      ConfirmationDlgComponent
   ],
   entryComponents: [ConfirmationDlgComponent]
})

export class SharedModule {
}

Și componenta de dialog (./confirmation-dlg.component.ts):

import {Component, Inject} from '@angular/core';
import {MAT_DIALOG_DATA} from '@angular/material';

@Component({
   selector: 'app-confirmation-dlg',
   template: `
      <div fxLayoutAlign="space-around" class="title colors" mat-dialog-title>{{data.title}}</div>
      <div class="msg" mat-dialog-content>
         {{data.msg}}
      </div>
      <a href="#"></a>
      <mat-dialog-actions fxLayoutAlign="space-around">
         <button mat-button [mat-dialog-close]="false" class="colors">No</button>
         <button mat-button [mat-dialog-close]="true" class="colors">Yes</button>
      </mat-dialog-actions>`,
   styles: [`
      .title {font-size: large;}
      .msg {font-size: medium;}
      .colors {color: white; background-color: #3f51b5;}
      button {flex-basis: 60px;}
   `]
})
export class ConfirmationDlgComponent {
   constructor(@Inject(MAT_DIALOG_DATA) public data: any) {}
}

Apoi o putem folosi în alt modul:

import {FlexLayoutModule} from '@angular/flex-layout';
import {NgModule} from '@angular/core';
import {GeneralComponent} from './general/general.component';
import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
import {CommonModule} from '@angular/common';
import {MaterialModule} from '../../material.module';

@NgModule({
   declarations: [
      GeneralComponent
   ],
   imports: [
      FlexLayoutModule,
      MaterialModule,
      CommonModule,
      NgbModule.forRoot()
   ],
   providers: []
})
export class SystemAdminModule {}

Manipulatorul de clic al componentei utilizează dialogul:

import {Component} from '@angular/core';
import {ConfirmationDlgComponent} from '../../../shared/confirmation-dlg.component';
import {MatDialog} from '@angular/material';

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

   constructor(private dialog: MatDialog) {}

   onWhateverClick() {
      const dlg = this.dialog.open(ConfirmationDlgComponent, {
         data: {title: 'Confirm Whatever', msg: 'Are you sure you want to whatever?'}
      });

      dlg.afterClosed().subscribe((whatever: boolean) => {
         if (whatever) {
            this.whatever();
         }
      });
   }

   whatever() {
      console.log('Do whatever');
   }
}

Doar folosind this.modal.open(MyComponent); așa cum ați făcut-o nu vă va returna un obiect la ale cărui evenimente să vă puteți abona, motiv pentru care nu puteți face ceva. Acest cod creează și deschide un dialog la ale cărui evenimente ne putem abona.

Dacă reduceți css-ul și html-ul, aceasta este o componentă simplă, dar dacă o scrieți dumneavoastră, veți avea control asupra designului și aspectului său, în timp ce o componentă pre-scrisă va trebui să fie mult mai grea pentru a vă oferi acest control.

Comentarii

  • Un răspuns bun, dar cred că plasarea componentei într-un modul partajat separat adaugă o complexitate care nu este necesară. –  > Por Stephen Turner.