Angular 2 einfache Möglichkeit, einen Bestätigungsdialog zu erstellen

73

Gibt es eine nicht so komplizierte Möglichkeit, einen Bestätigungsdialog in Winkel 2 zu erstellen ? Die Idee ist, auf ein Element zu klicken und dann ein Popup oder Modal anzuzeigen, um dessen Löschung zu bestätigen. Ich habe versucht, Winkel 2 Modale von hier Winkel 2 -Modal , aber Ich weiß nicht, wie ich das machen soll, wenn Sie bestätigen oder abbrechen, dass es etwas bewirkt. Die Klickfunktion funktioniert einwandfrei. Das einzige Problem ist, dass ich nicht genau weiß, wie ich sie verwenden soll. Ich habe auch ein anderes Modal mit dem gleichen Plugin mit dem Unterschied, den ich benutze.

this.modal.open(MyComponent);

Und ich möchte keine weitere Komponente erstellen, nur um ein Bestätigungsfeld anzuzeigen, deshalb frage ich.

Sieger dencowski
quelle
1
"Der einfache Weg" wäre, so etwas wie angle2-modal zu verwenden, wie Sie es erwähnt haben. Andernfalls müssen Sie sich einen bauen, und das kann ich nicht als einfachen Weg bezeichnen. Haben Sie auf dem von Ihnen angegebenen Link gesehen, dass es Plunker-Beispiele gibt, die die Verwendung zeigen :) embedded.plnkr.co/mbPzd8
AJT82
Ich sehe, dann ist es eine gute Idee, eine Komponente mit dem Bestätigungs-Popup zu erstellen, das 2 Schaltflächen hat, und wenn Sie darauf klicken, führen Sie eine Funktion in der Hauptkomponente aus. Im Beispiel benutzt er die Taste 5, um den Dialog zu schließen, den ich brauche, um ihn zu schließen und eine Funktion aufzurufen. Wie auch immer, ich werde versuchen, so einfach und klar wie möglich zu machen und Ergebnisse zu veröffentlichen
Sieger dencowski
Es gibt auch andere Modalitäten, die möglicherweise andere integrierte Funktionen haben, die Sie sich wünschen könnten, aber Ihre Anforderungen scheinen nicht allzu schwierig zu sein. Ich denke, viele wären für Sie geeignet, aber wenn Sie möchten, stöbern Sie einfach herum und finde eine, die du magst. Hier einige Beispiele: npmjs.com/search?q=angular+2+modal Probieren Sie sie aus und kehren Sie zu SO zurück, wenn Sie auf Probleme stoßen! Viel Spaß beim Codieren! :)
AJT82

Antworten:

173

Methode 1

Eine einfache Möglichkeit zur Bestätigung besteht darin, die Bestätigungswarnung des nativen Browsers zu verwenden. Die Vorlage kann eine Schaltfläche oder einen Link enthalten.

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

Und die Komponentenmethode kann wie folgt aussehen.

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

Methode 2

Eine andere Möglichkeit, einen einfachen Bestätigungsdialog zu erhalten, besteht darin, die eckigen Bootstrap-Komponenten wie ng-bootstrap oder ngx-bootstrap zu verwenden . Sie können die Komponente einfach installieren und die modale Komponente verwenden.

  1. Beispiele für Modalitäten mit ng-bootstrap
  2. Beispiele für Modalitäten mit ngx-bootstrap .

Methode 3

Im Folgenden finden Sie eine weitere Möglichkeit, ein einfaches Bestätigungs-Popup zu implementieren, angular2/materialdas ich in meinem Projekt implementiert habe.

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

Bestätigungsdialog.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;
}

Bestätigungsdialog.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 => folgendes Stylesheet hinzugefügt

<link rel="stylesheet" href="node_modules/@angular/material/core/theming/prebuilt/indigo-pink.css">
Philip John
quelle
1
Ich musste auch BrowserAnimationsModule von @ angle / platform-browser / animations und MaterialModule von @
angle
1
Auch für Stile, die ich @import '~@angular/material/prebuilt-themes/deeppurple-amber.css';folgend verwendet habe
estellezg
1
zurück ein Jahr später vergessen, eine gelöste hinzuzufügen. Derzeit bin ich in einem großen Projekt und habe mich für den matDialog entschieden, der vollständig, benutzerfreundlich und dennoch leistungsstark ist und Ihnen eine einfache Möglichkeit bietet, zwischen Ihrer Hauptkomponente und dem Dialog zu kommunizieren, wodurch so viele neue Optionen möglich sind. Wenn jemand dieses Problem hat, empfehle ich Ihnen, es zu versuchen, es erfordert einige Vorbereitung, aber es lohnt sich, da es einwandfrei funktioniert
Victor Dencowski
1
Funktioniert dies mit einer Rückruffunktion? Ich habe den Code nicht ausprobiert. Beim Lesen wird nur ein statisch typisierter Rückruf angezeigt. Wenn Sie beispielsweise einen dynamischen Aufruf ausführen möchten, z. B. etwas nach ID löschen möchten, müssen Sie einen Parameter analysieren und die Logik dort installieren.
KeaganFouche
1
+1. Dies ist ein sehr gutes Beispiel, das fast sofort funktioniert. Die neueste Version, ersetzen Sie einfach mdmit matund vielleicht noch einige in Stile für Buttons gebaut verwenden:mat-raised-button color="primary"
Alexei
36

Sie können window.confirm in Ihrer Funktion zusammen mit der if-Bedingung verwenden

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

Wenn Sie die Löschmethode aufrufen, wird eine Bestätigungsmeldung angezeigt. Wenn Sie auf OK klicken, wird die gesamte Logik innerhalb der if-Bedingung ausgeführt.

Tarek Badr
quelle
17

Ich bin ziemlich spät zur Party, aber hier ist eine andere Implementierung mit : https://stackblitz.com/edit/angular-confirmation-dialog

Bestätigungsdialog.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;
  }

}

Bestätigungsdialog.Komponente.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();
  }

}

Bestätigungsdialog.Komponente.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>

Verwenden Sie den Dialog wie folgt:

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)'));
  }
Tilo
quelle
Ich habe den obigen Code befolgt, aber wenn ich auf die Schaltfläche klicke, wird das Popup-Modal für den Bruchteil einer Sekunde angezeigt und verschwindet sofort. Können Sie mir helfen, dieses Problem zu beheben?
Watraplion
Passiert das auch mit der verknüpften StackBlitz-Demo?
Tilo
Nein .. In StackBlitz funktioniert es gut. Ich habe alle diese Dateien in meine Projektvorlage kopiert, wo ich vor diesem Problem
stehe
Nun, dies ist ohne weitere Informationen schwer (sprich: unmöglich) zu debuggen.
Tilo
@tilo: Es sieht so aus, als ob es nur in Angular 5 funktioniert. Nicht in Angular 4. Und was noch wichtiger ist, sie haben @Injectable () in späteren Versionen von ng-bootstrap
SK entfernt.
16

UPDATE: Plunkr hinzugefügt

Ich habe in allen Foren nach einer Lösung gesucht, aber keine gefunden. Deshalb habe ich eine Lösung mit der Javascript-Rückruffunktion der alten Schule gefunden. Dies ist eine sehr einfache und übersichtliche Methode, um einen Bestätigungsdialog zu erstellen und Rückruffunktionen für JA- und NEIN- Klickereignisse festzulegen.
Ich habe Bootstrap CSS für Modal und An Alert Service mit rxjs Subject verwendet.

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

Der wichtigste Teil ist hier 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();
          }
       }

Rufen Sie die Funktion von einer beliebigen Komponente aus auf

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

Plunkr https://embed.plnkr.co/vWBT2nWmtsXff0MXMKdd/

Sudeep Rane
quelle
Hallo. Ich suche so etwas. Aber der obige Code funktioniert nicht für mich. Kein Modal angezeigt und kein Fehler in console.tanks
mrapi
1
Hallo Mrpi, können Sie sicherstellen, dass Bootstrap-CSS vorhanden ist? Wenn Sie nun testen möchten, wie Ihr Modal aussieht, entfernen Sie ng-if und überprüfen Sie.
Sudeep Rane
Es funktioniert. Danke. Was ist mit der vertikalen Positionierung zur Mitte?
Mrapi
1
Sie müssen einige JS-Berechnungen durchführen, um dies vertikal durchzuführen. Dies kann nicht allein über CSS erfolgen. Aber für horizontalen Rand: 0 Auto funktioniert wie ein Zauber!
Sudeep Rane
@NasiruddinSaiyed: Kannst du bitte sagen, welche Module installiert werden sollen? Ich erhalte eine Warnung: WARNUNG in ./node_modules/@ng-bootstrap/ng-bootstrap/datepicker/datepicker-i18n.js 32: 39-56 "export 'getLocaleDayNames' wurde in '@ angle / common'
SK
7

Sie könnten sweetalert verwenden: https://sweetalert.js.org/guides/

npm install sweetalert --save

Importieren Sie es dann einfach in Ihre Anwendung:

import swal from 'sweetalert';

Wenn Sie zwei Argumente übergeben, ist das erste der Titel des Modals und das zweite der Text.

swal("Here's the title!", "...and here's the text!");
Lars Rødal
quelle
4

Hier ist eine etwas andere Einstellung, bei der die native Bestätigungsfunktion von Javascript und eine benutzerdefinierte Angular-Direktive verwendet werden. Es ist super flexibel und ziemlich leicht:

Verwendung:

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

Richtlinie:

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);
      }
    };
  }
}
Chris HG
quelle
1
Dies ist mein bevorzugter Ansatz aufgrund der Einfachheit und Wiederverwendbarkeit in einem.
Matt Brewerton
In Chrome musste ich die Klammern um hrsAreYouSure in der Schaltfläche entfernen, sonst würde es nicht funktionieren.
Reid
Wenn Sie die Eingabetaste drücken, während das Dialogfeld geöffnet ist, bestätigen Sie, ob dies Ihre Absicht war oder nicht.
Reid
2

Hinzufügen weiterer Optionen zur Antwort.

Du könntest benutzen npm i sweetalert2

Vergessen Sie nicht, den Stil zu Ihrem hinzuzufügen angular.json

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

Dann einfach importieren,

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


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

Boom, du bist bereit zu gehen.

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

Mehr dazu: - https://www.npmjs.com/package/sweetalert2

Ich hoffe das hilft jemandem.

Vielen Dank.

Anjana Silva
quelle
@ YuriWaki Ich bin froh, dass es geholfen hat :)
Anjana Silva
1

Um eine einzelne Implementierung des Bestätigungsdialogs in einer Anwendung mit mehreren Modulen wiederzuverwenden, muss der Dialog in einem separaten Modul implementiert werden. Hier ist eine Möglichkeit, dies mit Material Design und FxFlex zu tun, obwohl beide zurückgeschnitten oder ersetzt werden können.

Zuerst das gemeinsam genutzte Modul (./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 {
}

Und die Dialogkomponente (./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) {}
}

Dann können wir es in einem anderen Modul verwenden:

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

Der Klick-Handler der Komponente verwendet den folgenden Dialog:

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

Wenn this.modal.open(MyComponent);Sie nur das verwenden, was Sie getan haben, erhalten Sie kein Objekt zurück, dessen Ereignisse Sie abonnieren können. Deshalb können Sie es nicht dazu bringen, etwas zu tun. Dieser Code erstellt und öffnet einen Dialog, dessen Ereignisse wir abonnieren können.

Wenn Sie CSS und HTML zurückschneiden, ist dies wirklich eine einfache Komponente. Wenn Sie sie jedoch selbst schreiben, haben Sie die Kontrolle über Design und Layout, während eine vorab geschriebene Komponente viel schwerer sein muss, um diese Kontrolle zu erhalten.

Lars H.
quelle
Gute Antwort, aber ich denke, dass das Einfügen der Komponente in ein separates freigegebenes Modul die Komplexität erhöht, die nicht benötigt wird.
Stephen Turner