Bestätigungsdialog bei ng-click - AngularJS

85

Ich versuche, einen Bestätigungsdialog für ng-clickeine benutzerdefinierte AngularJS-Direktive einzurichten:

app.directive('ngConfirmClick', [
    function(){
        return {
            priority: 1,
            terminal: true,
            link: function (scope, element, attr) {
                var msg = attr.ngConfirmClick || "Are you sure?";
                var clickAction = attr.ngClick;
                element.bind('click',function (event) {
                    if ( window.confirm(msg) ) {
                        scope.$eval(clickAction)
                    }
                });
            }
        };
}])

Dies funktioniert gut, aber leider werden Ausdrücke innerhalb des Tags, die meine Direktive verwenden, nicht ausgewertet:

<button ng-click="sayHi()" ng-confirm-click="Would you like to say hi?">Say hi to {{ name }}</button>

(Name wird in diesem Fall nicht ausgewertet). Es scheint am Terminalparameter meiner Direktive zu liegen. Haben Sie Ideen zur Problemumgehung?

So testen Sie meinen Code: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview

poiuytrez
quelle
Warum verwenden Sie in diesem Fall Terminal? Es scheint, dass es ohne perfekt funktioniert (und Sie wissen es). Ich frage mich nur, warum Sie denken, dass dies in Ihrer Richtlinie notwendig ist.
Simon Belanger
@SimonBelanger Mit terminal = false wird sayHi () ausgelöst, auch wenn ich im Bestätigungsdialog auf "Abbrechen" klicke. Mein Ziel ist es nicht, sayHi () aufzurufen, wenn der Benutzer auf Abbrechen klickt.
Poiuytrez

Antworten:

92

Wenn es Ihnen nichts ausmacht, nicht zu verwenden ng-click, funktioniert es OK. Sie können es einfach in etwas anderes umbenennen und das Attribut trotzdem lesen, ohne zu vermeiden, dass der Klick-Handler zweimal ausgelöst wird.

http://plnkr.co/edit/YWr6o2?p=preview

Ich denke, das Problem besteht darin terminal, andere Anweisungen anzuweisen, nicht auszuführen. Die Datenbindung mit {{ }}ist nur ein Alias ​​für die ng-bindDirektive, die vermutlich von aufgehoben wird terminal.

mikel
quelle
13
Dieses Code-Snippet funktioniert nicht mehr mit der aktuellen Version von Angular. scope. $ eval (..) sollte durch scope ersetzt werden. $ apply (..)
CoolTapes
Bitte überprüfen Sie diese Frage für einen JS-Bestätigungsdialog mit E2E-Tests stackoverflow.com/questions/16424961/…
ndequeker
Dies funktioniert, aber was passiert, wenn ich das Kontrollkästchen "Diese Seite vermeiden, um zusätzliche Dialoge zu erstellen" des Chroms aktiviere? : s
Bigpony
57

Ein sauberer Richtlinienansatz.

Update: Alte Antwort (2014)

Es fängt das ng-clickEreignis grundsätzlich ab , zeigt die in der ng-confirm-click="message"Anweisung enthaltene Nachricht an und fordert den Benutzer zur Bestätigung auf. Wenn auf Bestätigen geklickt wird, wird der normale ng-clickVorgang ng-clickausgeführt. Andernfalls wird das Skript beendet und nicht ausgeführt.

<!-- index.html -->
<button ng-click="publish()" ng-confirm-click="You are about to overwrite your PUBLISHED content!! Are you SURE you want to publish?">
  Publish
</button>
// /app/directives/ng-confirm-click.js
Directives.directive('ngConfirmClick', [
  function(){
    return {
      priority: -1,
      restrict: 'A',
      link: function(scope, element, attrs){
        element.bind('click', function(e){
          var message = attrs.ngConfirmClick;
          // confirm() requires jQuery
          if(message && !confirm(message)){
            e.stopImmediatePropagation();
            e.preventDefault();
          }
        });
      }
    }
  }
]);

Code Kredit an Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Update: Neue Antwort (2016)

1) Das Präfix wurde von 'ng' in 'mw' geändert, da das erstere ('ng') nativen Winkelanweisungen vorbehalten ist.

2) Die Anweisung wurde geändert, um eine Funktion und eine Nachricht zu übergeben, anstatt das ng-click-Ereignis abzufangen.

3) Standard hinzugefügt "Sind Sie sicher?" Nachricht für den Fall, dass keine benutzerdefinierte Nachricht an mw-verify-click-message = "" bereitgestellt wird.

<!-- index.html -->
<button mw-confirm-click="publish()" mw-confirm-click-message="You are about to overwrite your PUBLISHED content!! Are you SURE you want to publish?">
  Publish
</button>
// /app/directives/mw-confirm-click.js
"use strict";

var module = angular.module( "myApp" );
module.directive( "mwConfirmClick", [
  function( ) {
    return {
      priority: -1,
      restrict: 'A',
      scope: { confirmFunction: "&mwConfirmClick" },
      link: function( scope, element, attrs ){
        element.bind( 'click', function( e ){
          // message defaults to "Are you sure?"
          var message = attrs.mwConfirmClickMessage ? attrs.mwConfirmClickMessage : "Are you sure?";
          // confirm() requires jQuery
          if( confirm( message ) ) {
            scope.confirmFunction();
          }
        });
      }
    }
  }
]);
mikeborgh
quelle
8
Nb, erfordert jQuery
Eggonlegs
1
Das funktioniert bei mir nicht. Keine Bestätigung wird angezeigt und der Klick wird fortgesetzt. Irgendjemand anderes?
OneHoopyFrood
Ich denke, es ist eine schlechte Idee, den ng-click click handler nicht zuerst zu lösen und sich dann darauf zu verlassen, sofort anzuhalten und Standardwerte zu verhindern
James Kleeh
OneHoopyFrood, Sie müssen eine gültige Funktion in ng-click = "" haben, sonst schlägt sie fehl. Vielen Dank.
Mikeborgh
Warum Schritt 2) Die Anweisung wurde geändert, um eine Funktion und eine Nachricht zu übergeben, anstatt das ng-click-Ereignis abzufangen?
Silber
46

Für mich, https://www.w3schools.com/js/js_popup.asp , hat das Standard-Bestätigungsdialogfeld des Browsers sehr gut funktioniert. habe gerade das ausprobiert:

$scope.delete = function() {
    if (confirm("sure to delete")) {
        // todo code for deletion
    }
};

Einfach .. :)
Aber ich denke, Sie können es nicht anpassen. Es wird mit der Schaltfläche "Abbrechen" oder "OK" angezeigt.

BEARBEITEN:

Wenn Sie ein ionisches Framework verwenden, müssen Sie den ionicPopup-Dialog wie folgt verwenden:

// A confirm dialog


$scope.showConfirm = function() {
   var confirmPopup = $ionicPopup.confirm({
     title: 'Delete',
     template: 'Are you sure you want to delete this item?'
   });

   confirmPopup.then(function(res) {
     if(res) {
       // Code to be executed on pressing ok or positive response
       // Something like remove item from list
     } else {
       // Code to be executed on pressing cancel or negative response
     }
   });
 };

Weitere Informationen finden Sie unter: $ ionicPopup

Kailas
quelle
Es sieht zwar sauber aus, aber ich denke, es ist gegen den deklarativen Ansatz in Angular. Mit diesem Ansatz ist es einfach, die Ansichtslogik in den Controller zu integrieren. Wenn dies möglich ist, kann es hilfreich sein, den Controller von UI-Elementen freizuhalten.
Jim Aho
1
Sie können das loswerden == true, was in diesem Fall völlig unnötig ist, da confirm()bereits ein Boolescher Wert zurückgegeben wird. Sie müssen JS nicht dazu bringen, erzwingen und mit true vergleichen.
Léo Lam
10

Es ist so einfach mit Core Javascript + Angular Js:

$scope.delete = function(id) 
    { 
       if (confirm("Are you sure?"))
           {
                //do your process of delete using angular js.
           }
   }

Wenn Sie auf OK klicken, wird der Löschvorgang ausgeführt, andernfalls nicht. * id ist der Parameter, Datensatz, den Sie löschen möchten.

VBMali
quelle
5

Sie möchten nicht verwenden, terminal: falseda dies die Verarbeitung innerhalb der Schaltfläche blockiert. Stattdessen in Ihrem linkdas klar attr.ngClickdas Standardverhalten zu verhindern.

http://plnkr.co/edit/EySy8wpeQ02UHGPBAIvg?p=preview

app.directive('ngConfirmClick', [
  function() {
    return {
      priority: 1,
      link: function(scope, element, attr) {
        var msg = attr.ngConfirmClick || "Are you sure?";
        var clickAction = attr.ngClick;
        attr.ngClick = "";
        element.bind('click', function(event) {
          if (window.confirm(msg)) {
            scope.$eval(clickAction)
          }
        });
      }
    };
  }
]);
Stepan Riha
quelle
Funktioniert in der Version von Angular, auf die Sie im Plunker verweisen. Wenn Sie jedoch auf ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js verweisen, funktioniert dies nicht wie erwartet.
ChrisW
Letztendlich funktioniert mein vorgeschlagener Ansatz nur in einigen Fällen, da ngClick weit mehr als nur eine einfache Bindung an 'click' bewirkt. Ich denke, der korrektere Ansatz besteht darin, die Bestätigung im ng-click-Handler und nicht über ein separates Attribut zu behandeln.
Stepan Riha
4

In der heutigen Zeit funktioniert diese Lösung für mich:

/**
 * A generic confirmation for risky actions.
 * Usage: Add attributes: ng-really-message="Are you sure"? ng-really-click="takeAction()" function
 */
angular.module('app').directive('ngReallyClick', [function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            element.bind('click', function() {
                var message = attrs.ngReallyMessage;
                if (message && confirm(message)) {
                    scope.$apply(attrs.ngReallyClick);
                }
            });
        }
    }
}]);

Credits: https://gist.github.com/asafge/7430497#file-ng-really-js

Nanu
quelle
4

Eine Nur-Winkel-Lösung, die nebeneinander funktioniert, ng-clickist möglich, indem der ng-clickAusdruck mit compile umbrochen wird .

Richtlinie:

.directive('confirmClick', function ($window) {
  var i = 0;
  return {
    restrict: 'A',
    priority:  1,
    compile: function (tElem, tAttrs) {
      var fn = '$$confirmClick' + i++,
          _ngClick = tAttrs.ngClick;
      tAttrs.ngClick = fn + '($event)';

      return function (scope, elem, attrs) {
        var confirmMsg = attrs.confirmClick || 'Are you sure?';

        scope[fn] = function (event) {
          if($window.confirm(confirmMsg)) {
            scope.$eval(_ngClick, {$event: event});
          }
        };
      };
    }
  };
});

HTML:

<a ng-click="doSomething()" confirm-click="Are you sure you wish to proceed?"></a>
scarlz
quelle
3
    $scope.MyUpdateFunction = function () {
        var retVal = confirm("Do you want to save changes?");
        if (retVal == true) {
            $http.put('url', myData).
            success(function (data, status, headers, config) {
                alert('Saved');
            }).error(function (data, status, headers, config) {
                alert('Error while updating');
            });
            return true;
        } else {
            return false;
        }
    }

Code sagt alles

om471987
quelle
1

HTML 5 Codebeispiel

<button href="#" ng-click="shoutOut()" confirmation-needed="Do you really want to
shout?">Click!</button>

Codebeispiel für die benutzerdefinierte Richtlinie von AngularJ

var app = angular.module('mobileApp', ['ngGrid']);
app.directive('confirmationNeeded', function () {
    return {
    link: function (scope, element, attr) {
      var msg = attr.confirmationNeeded || "Are you sure?";
      var clickAction = attr.ngClick;
      element.bind('click',function (e) {
        scope.$eval(clickAction) if window.confirm(msg)
        e.stopImmediatePropagation();
        e.preventDefault();
       });
     }
    };
});
Anil Singh
quelle
1

Der Bestätigungsdialog kann mit AngularJS Material implementiert werden :

$ mdDialog öffnet einen Dialog über die App, um Benutzer über wichtige Informationen zu informieren oder sie zu verpflichten, Entscheidungen zu treffen. Es gibt zwei Ansätze für die Einrichtung: eine einfache Versprechen-API und eine reguläre Objektsyntax.

Implementierungsbeispiel: Winkelmaterial - Dialoge

Genauso wie
quelle
0

Wenn Sie einen UI-Router verwenden, ersetzt die Schaltfläche Abbrechen oder Akzeptieren die URL. Um dies zu verhindern, können Sie in jedem Fall des bedingten Satzes false wie folgt zurückgeben:

app.directive('confirmationNeeded', function () {
  return {
    link: function (scope, element, attr) {
      var msg = attr.confirmationNeeded || "Are you sure?";
      var clickAction = attr.confirmedClick;
      element.bind('click',function (event) {
      if ( window.confirm(msg) )
        scope.$eval(clickAction);
      return false;
    });
  }
}; });
Juanma Jurado
quelle
0

Eine sehr einfache Winkellösung

Sie können id mit oder ohne Nachricht verwenden. Ohne Nachricht wird die Standardnachricht angezeigt.

Richtlinie

app.directive('ngConfirmMessage', [function () {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.on('click', function (e) {
                var message = attrs.ngConfirmMessage || "Are you sure ?";
                if (!confirm(message)) {
                    e.stopImmediatePropagation();
                }
            });
        }
    }
}]);

Regler

$scope.sayHello = function(){
    alert("hello")
}

HTML

Mit einer Nachricht

<span ng-click="sayHello()" ng-confirm-message="Do you want to say Hello ?" >Say Hello!</span>

Ohne eine Nachricht

<span ng-click="sayHello()" ng-confirm-message>Say Hello!</span>
Merlin
quelle
0

Hier ist eine saubere und einfache Lösung Winkel Versprechen mit $q, $windowund nativer .confirm()modal:

angular.module('myApp',[])
  .controller('classicController', ( $q, $window ) => {
    this.deleteStuff = ( id ) => {
      $q.when($window.confirm('Are you sure ?'))
        .then(( confirm ) => {
          if ( confirm ) {
            // delete stuff
          }
        });
    };
  });

Hier verwende ich controllerAsSyntax- und ES6-Pfeilfunktionen, aber es funktioniert auch in einfachem alten ES5.

Freezystem
quelle
0

Löschen Sie das Bestätigungs-Popup mit dem Bootstrap in anglejs

Sehr einfach. Ich habe eine Lösung dafür mit der Verwendung von Bootstrap-Konformations-Popup. Hier bin ich zur Verfügung gestellt

<button ng-click="deletepopup($index)">Delete</button>

im Bootstrap-Modell-Popup:

<div class="modal-footer">
  <a href="" data-dismiss="modal" ng-click="deleteData()">Yes</a>
  <a href="" data-dismiss="modal">No</a>
</div>

js

var index=0;
$scope.deleteData=function(){
    $scope.model.contacts.splice(index,1);
}
// delete a row 
$scope.deletepopup = function ($index) {
    index=$index;
    $('#myModal').modal('show');
};

Wenn ich auf die Schaltfläche Löschen klicke, wird das Bootstrap-Popup zum Löschen der Konformation geöffnet und wenn ich auf Ja klicke, wird die Schaltflächenzeile gelöscht.

Rama Krishna
quelle
-1

Ich wünschte, AngularJS hätte einen eingebauten Bestätigungsdialog. Oft ist es besser, einen benutzerdefinierten Dialog zu haben, als den eingebauten Browser zu verwenden.

Ich habe den Twitter-Bootstrap kurz verwendet, bis er mit Version 6 eingestellt wurde. Ich habe mich nach Alternativen umgesehen, aber die, die ich gefunden habe, waren kompliziert. Ich habe mich für die JQuery-Benutzeroberfläche entschieden.

Hier ist mein Beispiel, das ich aufrufe, wenn ich etwas aus dem ng-Gitter entfernen möchte.

    // Define the Dialog and its properties.
    $("<div>Are you sure?</div>").dialog({
        resizable: false,
        modal: true,
        title: "Modal",
        height: 150,
        width: 400,
        buttons: {
            "Yes": function () {
                $(this).dialog('close');
                //proceed with delete...
                /*commented out but left in to show how I am using it in angular
                var index = $scope.myData.indexOf(row.entity);

                $http['delete']('/EPContacts.svc/json/' + $scope.myData[row.rowIndex].RecordID).success(function () { console.log("groovy baby"); });

                $scope.gridOptions.selectItem(index, false);
                $scope.myData.splice(index, 1);
                */
            },
            "No": function () {
                $(this).dialog('close');
                return;
            }
        }
    });

Ich hoffe das hilft jemandem. Ich habe mir die Haare ausgezogen, als ich ui-bootstrap-tpls.js aktualisieren musste, aber es hat meinen bestehenden Dialog unterbrochen. Ich bin heute Morgen zur Arbeit gekommen, habe ein paar Dinge ausprobiert und dann festgestellt, dass ich zu kompliziert war.

Doug Weems
quelle