Diálogo de confirmación en ng-click - AngularJS

85

Estoy tratando de configurar un cuadro de diálogo de confirmación ng-clickutilizando una directiva angularjs personalizada:

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

Esto funciona muy bien, pero desafortunadamente, las expresiones dentro de la etiqueta que usan mi directiva no se evalúan:

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

(el nombre no se evalúa en este caso). Parece deberse al parámetro terminal de mi directiva. ¿Tiene alguna idea de solución?

Para probar mi código: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview

poiuytrez
fuente
¿Por qué usa terminal en este caso? Parece que funciona perfectamente sin (y lo sabes). Me pregunto por qué cree que es necesario en su directiva.
Simon Belanger
@SimonBelanger Con terminal = false, incluso si hago clic en "cancelar" en el cuadro de diálogo de confirmación, se activa sayHi (). Mi objetivo no es llamar a sayHi () si el usuario hace clic en cancelar.
poiuytrez

Respuestas:

92

Si no le importa no usar ng-click, funciona bien. Puede simplemente cambiarle el nombre a otra cosa y aún leer el atributo, mientras evita que el controlador de clic se active dos veces, el problema que existe en este momento.

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

Creo que el problema es que terminalordena a otras directivas que no se ejecuten. La vinculación de datos con {{ }}es solo un alias de la ng-binddirectiva, que presumiblemente está cancelada por terminal.

mikel
fuente
13
Este fragmento de código ya no funciona con la versión actual de angular. alcance. $ eval (..) debe reemplazarse con alcance. $ aplicar (..)
CoolTapes
Por favor, consulte esta pregunta para ver un cuadro de diálogo de confirmación JS con E2E-tests stackoverflow.com/questions/16424961/…
ndequeker
Esto funciona, pero ¿qué sucede si marco la casilla de verificación de Chrome "Evitar esta página para crear diálogos adicionales"? : s
bigpony
58

Un enfoque directivo limpio.

Actualización: Respuesta antigua (2014)

Básicamente intercepta el ng-clickevento, muestra el mensaje contenido en la ng-confirm-click="message"directiva y pide al usuario que confirme. Si se hace clic en confirmar, se ng-clickejecuta normalmente , si no, el script termina y ng-clickno se ejecuta.

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

Crédito del código para Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Actualización: Nueva respuesta (2016)

1) Se cambió el prefijo de 'ng' a 'mw' ya que el primero ('ng') está reservado para las directivas angulares nativas.

2) Directiva modificada para pasar una función y un mensaje en lugar de interceptar el evento ng-click.

3) Agregado predeterminado "¿Estás seguro?" mensaje en el caso de que no se proporcione un mensaje personalizado a 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();
          }
        });
      }
    }
  }
]);
mikeborgh
fuente
8
Nb, requiere jQuery
eggonlegs
1
Esto no me funciona. No se muestra ninguna confirmación y el clic continúa. ¿Alguien mas?
OneHoopyFrood
Creo que es una mala idea no desvincular primero el controlador de clic ng-click y luego confiar en la parada inmediata y evitar el defecto
James Kleeh
OneHoopyFrood, debe tener una función válida en ng-click = "" o de lo contrario fallará. Gracias.
Mikeborgh
¿Por qué el paso 2) Directiva modificada para pasar una función y un mensaje en lugar de interceptar el evento ng-click?
Silver
46

Para mí, https://www.w3schools.com/js/js_popup.asp , el cuadro de diálogo de confirmación predeterminado del navegador funcionó mucho. acabo de probar esto:

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

Simple .. :)
Pero creo que no se puede personalizar. Aparecerá con el botón "Cancelar" o "Aceptar".

EDITAR:

En caso de que esté utilizando un marco iónico, debe usar el cuadro de diálogo ionicPopup como en:

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

Para obtener más detalles, consulte: $ ionicPopup

Kailas
fuente
De hecho, se ve limpio, sin embargo, creo que está en contra del enfoque declarativo en Angular. Es fácil poner la lógica de la vista dentro del controlador con este enfoque. Si se puede, puede ser útil mantener el controlador limpio de elementos de la interfaz de usuario.
Jim Aho
1
Puede deshacerse de == true, que es completamente innecesario en este caso, porque confirm()ya devuelve un booleano. No es necesario que JS escriba coaccionarlo y compararlo con verdadero.
Léo Lam
10

Es tan simple usar core javascript + angular js:

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

Si hace clic en Aceptar, se llevará a cabo la operación de eliminación; de lo contrario, no. * id es el parámetro, registro que desea eliminar.

VBMali
fuente
5

No desea usarlo, terminal: falseya que eso es lo que bloquea el procesamiento del interior del botón. En cambio, en su linkclaro attr.ngClickpara evitar el comportamiento predeterminado.

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
fuente
Funciona en la versión de Angular a la que hace referencia en plunker, pero si hace referencia a ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js, no funciona como se esperaba.
ChrisW
En última instancia, mi enfoque sugerido solo funciona para algunos casos, porque ngClick hace mucho más que un simple enlace a 'hacer clic'. Creo que el enfoque más correcto es lidiar con la confirmación en el controlador ng-click en lugar de a través de un atributo separado.
Stepan Riha
4

En la fecha de hoy, esta solución me funciona:

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

Créditos: https://gist.github.com/asafge/7430497#file-ng-really-js

Nanu
fuente
4

Es posible una solución solo angular que funcione junto ng-clickcon compilar para envolver la ng-clickexpresión.

Directiva:

.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
fuente
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;
        }
    }

El código lo dice todo

om471987
fuente
1

Ejemplo de código HTML 5

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

Ejemplo de código de directiva personalizada de AngularJs

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

El cuadro de diálogo de confirmación se puede implementar usando AngularJS Material :

$ mdDialog abre un cuadro de diálogo sobre la aplicación para informar a los usuarios sobre información crítica o solicitarles que tomen decisiones. Hay dos enfoques para la configuración: una API de promesa simple y una sintaxis de objeto normal.

Ejemplo de implementación: Material angular - Diálogos

Tal como
fuente
0

Si usa ui-router, el botón cancelar o aceptar reemplaza la URL. Para evitar esto, puede devolver falso en cada caso de la oración condicional de esta manera:

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

Una solución angular muy simple

Puede usar id con un mensaje o sin él. Sin mensaje, se mostrará el mensaje predeterminado.

Directiva

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

Controlador

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

HTML

Con un mensaje

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

Sin un mensaje

<span ng-click="sayHello()" ng-confirm-message>Say Hello!</span>
Esmerejón
fuente
0

Aquí es una solución limpia y sencilla mediante promesas angulares $q, $windowy nativa .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
          }
        });
    };
  });

Aquí estoy usando la controllerAssintaxis y las funciones de flecha de ES6, pero también funciona en ES5.

Freezystem
fuente
0

Eliminar ventana emergente de confirmación usando bootstrap en angularjs

muy simple .. Tengo una solución para esto con el uso de la ventana emergente de conformación de arranque. Aquí estoy proporcionado

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

en la ventana emergente del modelo bootstrap:

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

cuando hago clic en el botón Eliminar, se abrirá una ventana emergente de conformación de eliminación de arranque y cuando hago clic en el botón Sí, se eliminará la fila.

Rama Krishna
fuente
0

ng-click retorno confirmar 100% funciona

en el archivo html, llame a la función delete_plot ()

<i class="fa fa-trash delete-plot" ng-click="delete_plot()"></i> 
 
  

Agrega esto a tu controlador

    $scope.delete_plot = function(){
        check = confirm("Are you sure to delete this plot?")
        if(check){
            console.log("yes, OK pressed")
        }else{
            console.log("No, cancel pressed")

        }
    }
azhar
fuente
-1

Ojalá AngularJS tuviera un cuadro de diálogo de confirmación integrado. A menudo, es mejor tener un cuadro de diálogo personalizado que usar el del navegador integrado.

Utilicé brevemente el bootstrap de twitter hasta que se suspendió con la versión 6. Busqué alternativas, pero las que encontré eran complicadas. Decidí probar la interfaz de usuario de JQuery.

Aquí está mi muestra que llamo cuando estoy a punto de eliminar algo de ng-grid;

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

Espero que esto ayude a alguien. Estaba tirando de mi cabello cuando necesitaba actualizar ui-bootstrap-tpls.js pero rompió mi diálogo existente. Llegué al trabajo esta mañana, probé algunas cosas y luego me di cuenta de que me estaba complicando demasiado.

Doug Weems
fuente