Confirmation dialog on ng-click - AngularJS

252,818

Solution 1

If you don't mind not using ng-click, it works OK. You can just rename it to something else and still read the attribute, while avoiding the click handler being triggered twice problem there is at the moment.

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

I think the problem is terminal instructs other directives not to run. Data-binding with {{ }} is just an alias for the ng-bind directive, which is presumably cancelled by terminal.

Solution 2

A clean directive approach.

Update: Old Answer (2014)

It basically intercepts the ng-click event, displays the message contained in the ng-confirm-click="message" directive and asks the user to confirm. If confirm is clicked the normal ng-click executes, if not the script terminates and ng-click is not run.

<!-- 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 credit to Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Update: New Answer (2016)

1) Changed prefix from 'ng' to 'mw' as the former ('ng') is reserved for native angular directives.

2) Modified directive to pass a function and message instead of intercepting ng-click event.

3) Added default "Are you sure?" message in the case that a custom message is not provided to mw-confirm-click-message="".

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

Solution 3

For me, https://www.w3schools.com/js/js_popup.asp, the default confirmation dialog box of the browser worked a great deal. just tried out this:

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

Simple.. :)
But I think you can't customize it. It will appear with "Cancel" or "Ok" button.

EDIT:

In case you are using ionic framework, you need to use the ionicPopup dialog as in:

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

For more details, refer: $ionicPopup

Solution 4

Its so simple using core javascript + angular js:

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

If you click OK, then delete operation will take, otherwise not. * id is the parameter, record that you want to delete.

Solution 5

You don't want to use terminal: false since that's what's blocking the processing of inside the button. Instead, in your link clear the attr.ngClick to prevent the default behavior.

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)
          }
        });
      }
    };
  }
]);
Share:
252,818

Related videos on Youtube

poiuytrez
Author by

poiuytrez

Updated on October 16, 2021

Comments

  • poiuytrez
    poiuytrez over 2 years

    I am trying to setup a confirmation dialog on an ng-click using a custom angularjs directive:

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

    This works great but unfortunately, expressions inside the tag using my directive are not evaluated:

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

    (name is not evaluated is this case). It seems to be due to the terminal parameter of my directive. Do you have any ideas of workaround?

    To test my code: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview

    • Simon Belanger
      Simon Belanger over 10 years
      Why do you use terminal in this case ? It seems that it works perfectly without (and you know it). I just wonder why you think it's necessary in your directive.
    • poiuytrez
      poiuytrez over 10 years
      @SimonBelanger With terminal = false, even if I click on "cancel" in the confirmation dialog, sayHi() is triggered. My goal is not to call sayHi() if the user clicks on cancel.
  • ChrisW
    ChrisW about 10 years
    Works in the version of Angular that you reference in plunker, but if you reference ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.j‌​s it doesn't work as expected.
  • Stepan Riha
    Stepan Riha about 10 years
    Ultimatelly my suggested approach only work for some cases, because ngClick does way more than simlpy binding to 'click'. I think the more correct approach is to deal with the confirmation in the ng-click handler rather than via a separate attribute.
  • CoolTapes
    CoolTapes almost 10 years
    This code snippet no longer works with the current version of angular. scope.$eval(..) should be replaced with scope.$apply(..)
  • ndequeker
    ndequeker over 9 years
    please check this question for a JS confirmation dialog with E2E-tests stackoverflow.com/questions/16424961/…
  • eggonlegs
    eggonlegs over 9 years
    N.b., requires jQuery
  • Jim Aho
    Jim Aho about 9 years
    It does indeed look clean, however I think it's against the declarative approach in Angular. It's easy to put view logic inside the controller with this approach. If one can, it can be helpful to keep the controller clean from UI elements.
  • Léo Lam
    Léo Lam almost 9 years
    You can get rid of the == true, which is completely unnecessary in this case, because confirm() already returns a boolean. No need to get JS to type coerce it and compare it to true.
  • OneHoopyFrood
    OneHoopyFrood almost 9 years
    This isn't working for me. No confirm shows and the click continues. Anyone else?
  • James Kleeh
    James Kleeh over 8 years
    I think it is a bad idea to not unbind the ng-click click handler first and then rely on stop immediate and prevent default
  • 0x777
    0x777 over 8 years
    This works, but what happens if I check the chrome's checkbox "Avoid this page to create additional dialogs" ? :s
  • mikeborgh
    mikeborgh almost 8 years
    OneHoopyFrood, you must have a valid function in ng-click="" or else it fails. Thanks.
  • Silver
    Silver almost 8 years
    Why step 2) Modified directive to pass a function and message instead of intercepting ng-click event?
  • Azhar Mansuri
    Azhar Mansuri over 7 years
    When I use mwConfirmClick it works fine. But my view didn't update as per scope. When I use ng-click, it updates my view automatically. So could you please help me how can I update view using mwConfirmClick?