Caixa de diálogo de confirmação no ng-click - AngularJS

85

Estou tentando configurar uma caixa de diálogo de confirmação ng-clickusando uma diretiva 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)
                    }
                });
            }
        };
}])

Isso funciona muito bem, mas, infelizmente, as expressões dentro da tag usando minha diretiva não são avaliadas:

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

(o nome não é avaliado neste caso). Parece ser devido ao parâmetro terminal da minha diretiva. Você tem alguma ideia de solução alternativa?

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

Poiuytrez
fonte
Por que você usa o terminal neste caso? Parece que funciona perfeitamente sem (e você sabe disso). Eu só me pergunto por que você acha que é necessário em sua diretiva.
Simon Belanger
@SimonBelanger Com terminal = false, mesmo se eu clicar em "cancelar" na caixa de diálogo de confirmação, diga Hi () será acionado. Meu objetivo não é chamar sayHi () se o usuário clicar em cancelar.
poiuytrez

Respostas:

92

Se você não se importa em não usar ng-click, funciona bem. Você pode simplesmente renomeá-lo para outra coisa e ainda ler o atributo, evitando que o manipulador de cliques seja disparado duas vezes, problema que existe no momento.

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

Acho que o problema é terminalinstruir outras diretivas para não executar. A vinculação de dados com {{ }}é apenas um alias para a ng-binddiretiva, que é presumivelmente cancelada por terminal.

Michael Low
fonte
13
Este trecho de código não funciona mais com a versão atual do angular. scope. $ eval (..) deve ser substituído por scope. $ apply (..)
CoolTapes de
verifique esta questão para uma caixa de diálogo de confirmação JS com E2E-tests stackoverflow.com/questions/16424961/…
ndequeker
Isso funciona, mas o que acontece se eu marcar a caixa de seleção do cromo "Evite esta página para criar caixas de diálogo adicionais"? : s
bigpony de
58

Uma abordagem diretiva limpa.

Atualização: Resposta Antiga (2014)

Basicamente, ele intercepta o ng-clickevento, exibe a mensagem contida na ng-confirm-click="message"diretiva e solicita a confirmação do usuário. Se confirmar for clicado, o normal é ng-clickexecutado; caso contrário, o script termina e ng-clicknão é executado.

<!-- 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 do código para Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Atualização: Nova Resposta (2016)

1) Prefixo alterado de 'ng' para 'mw', pois o anterior ('ng') é reservado para diretivas angulares nativas.

2) Diretiva modificada para passar uma função e mensagem em vez de interceptar o evento ng-click.

3) Adicionado o padrão "Tem certeza?" mensagem no caso de uma mensagem personalizada não ser fornecida para 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
fonte
8
Nb, requer jQuery
eggonlegs
1
Isso não está funcionando para mim. Nenhuma confirmação é exibida e o clique continua. Alguém mais?
OneHoopyFrood
Acho que é uma má ideia não desvincular o manipulador ng-click primeiro e, em seguida, confiar em parar imediatamente e evitar o padrão
James Kleeh
OneHoopyFrood, você deve ter uma função válida em ng-click = "" ou então ele falhará. Obrigado.
Mikeborgh
Por que etapa 2) Diretiva modificada para passar uma função e mensagem em vez de interceptar o evento ng-click?
Prata
46

Para mim, https://www.w3schools.com/js/js_popup.asp , a caixa de diálogo de confirmação padrão do navegador funcionou muito bem. acabei de experimentar isto:

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

Simples .. :)
Mas acho que você não pode personalizá-lo. Ele aparecerá com o botão "Cancelar" ou "Ok".

EDITAR:

Caso você esteja usando uma estrutura iônica, é necessário usar a caixa de diálogo ionicPopup como em:

// 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 mais detalhes, consulte: $ ionicPopup

Kailas
fonte
De fato, parece limpo, mas acho que vai contra a abordagem declarativa do Angular. É fácil colocar a lógica de exibição dentro do controlador com essa abordagem. Se for possível, pode ser útil manter o controlador limpo de elementos da IU.
Jim Aho,
1
Você pode se livrar do == true, o que é completamente desnecessário neste caso, porque confirm()já retorna um booleano. Não há necessidade de obter JS para digitar, coagi-lo e compará-lo com verdadeiro.
Léo Lam
10

É tão simples usar o núcleo javascript + angular js:

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

Se você clicar em OK, a operação de exclusão ocorrerá; caso contrário, não. * id é o parâmetro, registro que você deseja excluir.

VBMali
fonte
5

Você não deseja usar, terminal: falsepois é isso que está bloqueando o processamento de dentro do botão. Em vez disso, em seu linkclaro oattr.ngClick para evitar o comportamento padrão.

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
fonte
Funciona na versão do Angular que você faz referência no plunker, mas se você faz referência a ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js, não funciona conforme o esperado.
ChrisW
No final das contas, minha abordagem sugerida só funciona em alguns casos, porque o ngClick faz muito mais do que uma simples vinculação ao 'clique'. Acho que a abordagem mais correta é lidar com a confirmação no manipulador ng-click em vez de por meio de um atributo separado.
Stepan Riha
4

Na data de hoje, esta solução funciona para mim:

/**
 * 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
fonte
4

Uma solução apenas angular que funciona paralelamente ng-clické possível usando compilar para envolver a ng-clickexpressão.

Diretriz:

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

Código diz tudo

om471987
fonte
1

Amostra de código HTML 5

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

Amostra de código da diretiva personalizada 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
fonte
1

A caixa de diálogo de confirmação pode ser implementada usando o material AngularJS :

$ mdDialog abre uma caixa de diálogo sobre o aplicativo para informar os usuários sobre informações críticas ou exigir que tomem decisões. Existem duas abordagens para configuração: uma API de promessa simples e sintaxe de objeto regular.

Exemplo de implementação: Angular Material - Diálogos

Justinas Jakavonis
fonte
0

Se você usa ui-roteador, o botão cancelar ou aceitar substituirá o url. Para evitar isso, você pode retornar falso em cada caso da sentença condicional como esta:

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

Uma solução angular muito simples

Você pode usar id com uma mensagem ou sem. Sem mensagem, a mensagem padrão será exibida.

Diretriz

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

Com uma mensagem

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

Sem mensagem

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

Aqui está uma solução limpa e simples, utilizando promessas angulares $q, $windowe 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
          }
        });
    };
  });

Aqui estou usando a controllerAssintaxe e as funções de seta do ES6, mas também está funcionando no ES5.

Freezystem
fonte
0

Apague o popup de confirmação usando bootstrap no angularjs

muito simples .. Eu tenho uma solução para isso usando o pop-up de conformação de bootstrap. Aqui estou eu

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

no pop-up do modelo de 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');
};

Quando eu clico no botão Excluir bootstrap, o pop-up de confirmação de exclusão é aberto e quando eu clico no botão Sim, a linha é excluída.

Rama Krishna
fonte
0

ng-click retornar confirmar 100% funciona

no arquivo html, chame a função delete_plot ()

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

Adicione isso ao seu 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
fonte
-1

Gostaria que o AngularJS tivesse uma caixa de diálogo de confirmação embutida. Freqüentemente, é melhor ter uma caixa de diálogo personalizada do que usar o do navegador embutido.

Usei brevemente o bootstrap do Twitter até que ele foi descontinuado com a versão 6. Procurei alternativas, mas as que encontrei eram complicadas. Decidi experimentar o JQuery UI.

Aqui está meu exemplo que chamo quando estou prestes a remover algo do 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 isso ajude alguém. Eu estava puxando meu cabelo quando precisei atualizar ui-bootstrap-tpls.js, mas quebrou minha caixa de diálogo existente. Cheguei ao trabalho esta manhã, tentei algumas coisas e então percebi que estava complicando demais.

Doug Weems
fonte