Boîte de dialogue de confirmation sur ng-click - AngularJS

85

J'essaie de configurer une boîte de dialogue de confirmation sur un en ng-clickutilisant une directive angularjs personnalisée:

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

Cela fonctionne très bien mais malheureusement, les expressions à l'intérieur de la balise utilisant ma directive ne sont pas évaluées:

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

(le nom n'est pas évalué dans ce cas). Cela semble être dû au paramètre terminal de ma directive. Avez-vous des idées de contournement?

Pour tester mon code: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview

poiuytrez
la source
Pourquoi utilisez-vous un terminal dans ce cas? Il semble que cela fonctionne parfaitement sans (et vous le savez). Je me demande simplement pourquoi vous pensez que c'est nécessaire dans votre directive.
Simon Belanger
@SimonBelanger Avec terminal = false, même si je clique sur "annuler" dans la boîte de dialogue de confirmation, sayHi () se déclenche. Mon objectif n'est pas d'appeler sayHi () si l'utilisateur clique sur annuler.
poiuytrez

Réponses:

92

Si cela ne vous dérange pas de ne pas utiliser ng-click, cela fonctionne bien. Vous pouvez simplement le renommer en autre chose et toujours lire l'attribut, tout en évitant que le gestionnaire de clics ne soit déclenché deux fois le problème qui se produit actuellement.

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

Je pense que le problème est que terminalles autres directives ne doivent pas être exécutées. La liaison de données avec {{ }}n'est qu'un alias de la ng-binddirective, qui est vraisemblablement annulée par terminal.

mikel
la source
13
Cet extrait de code ne fonctionne plus avec la version actuelle d'angular. scope. $ eval (..) doit être remplacé par scope. $ apply (..)
CoolTapes
veuillez vérifier cette question pour une boîte de dialogue de confirmation JS avec E2E-tests stackoverflow.com/questions/16424961
...
Cela fonctionne, mais que se passe-t-il si je coche la case à cocher du chrome "Éviter cette page pour créer des boîtes de dialogue supplémentaires"? : s
bigpony
58

Une approche directive propre.

Mise à jour: ancienne réponse (2014)

Il intercepte essentiellement l' ng-clickévénement, affiche le message contenu dans la ng-confirm-click="message"directive et demande à l'utilisateur de confirmer. Si vous cliquez sur Confirmer ng-click, la procédure normale s'exécute, sinon le script se termine et ng-clickn'est pas exécuté.

<!-- 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édit de code à Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Mise à jour: nouvelle réponse (2016)

1) Changement du préfixe de 'ng' à 'mw' car l'ancien ('ng') est réservé aux directives angulaires natives.

2) Directive modifiée pour transmettre une fonction et un message au lieu d'intercepter l'événement ng-click.

3) Ajout par défaut "Êtes-vous sûr?" message dans le cas où un message personnalisé n'est pas fourni à 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
la source
8
Nb, nécessite jQuery
eggonlegs
1
Cela ne fonctionne pas pour moi. Aucune confirmation ne s'affiche et le clic continue. Quelqu'un d'autre?
OneHoopyFrood
Je pense que c'est une mauvaise idée de ne pas dissocier d'abord le gestionnaire de clics ng-click, puis de s'appuyer sur l'arrêt immédiat et d'éviter les défauts
James Kleeh
OneHoopyFrood, vous devez avoir une fonction valide dans ng-click = "" sinon cela échoue. Merci.
mikeborgh
Pourquoi l'étape 2) Directive modifiée pour passer une fonction et un message au lieu d'intercepter l'événement ng-click?
Argent
46

Pour moi, https://www.w3schools.com/js/js_popup.asp , la boîte de dialogue de confirmation par défaut du navigateur fonctionnait beaucoup. vient d'essayer ceci:

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

Simple .. :)
Mais je pense que vous ne pouvez pas le personnaliser. Il apparaîtra avec le bouton "Annuler" ou "Ok".

ÉDITER:

Dans le cas où vous utilisez un framework ionique, vous devez utiliser la boîte de dialogue ionicPopup comme dans:

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

Pour plus de détails, consultez: $ ionicPopup

Kailas
la source
Cela semble en effet propre, mais je pense que c'est contre l'approche déclarative dans Angular. Il est facile de mettre la logique de vue à l'intérieur du contrôleur avec cette approche. Si vous le pouvez, il peut être utile de garder le contrôleur propre des éléments de l'interface utilisateur.
Jim Aho
1
Vous pouvez vous débarrasser du == true, ce qui est complètement inutile dans ce cas, car confirm()renvoie déjà un booléen. Inutile de demander à JS de le taper et de le comparer à vrai.
Léo Lam
10

C'est tellement simple d'utiliser le noyau javascript + angular js:

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

Si vous cliquez sur OK, l'opération de suppression prendra, sinon pas. * id est le paramètre, enregistrement que vous souhaitez supprimer.

VBMali
la source
5

Vous ne voulez pas utiliser terminal: falsecar c'est ce qui bloque le traitement à l'intérieur du bouton. Au lieu de cela, dans votrelink clair leattr.ngClick pour empêcher le comportement par défaut.

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)
          }
        });
      }
    };
  }
]);
Stépan Riha
la source
Fonctionne dans la version d'Angular que vous référencez dans plunker, mais si vous référencez ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js cela ne fonctionne pas comme prévu.
ChrisW
En fin de compte, mon approche suggérée ne fonctionne que dans certains cas, car ngClick fait bien plus qu'une simple liaison au «clic». Je pense que l'approche la plus correcte consiste à traiter la confirmation dans le gestionnaire ng-click plutôt que via un attribut séparé.
Stepan Riha
4

À la date d'aujourd'hui, cette solution fonctionne pour moi:

/**
 * 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édits: https://gist.github.com/asafge/7430497#file-ng-really-js

Nanu
la source
4

Une solution angulaire uniquement qui fonctionne parallèlement ng-clickest possible en utilisant compile pour envelopper l' ng-clickexpression.

Directif:

.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
la source
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;
        }
    }

Le code dit tout

om471987
la source
1

Exemple de code HTML 5

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

Exemple de code de directive personnalisée 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
la source
1

La boîte de dialogue de confirmation peut être implémentée à l'aide du matériau AngularJS :

$ mdDialog ouvre une boîte de dialogue sur l'application pour informer les utilisateurs des informations critiques ou leur demander de prendre des décisions. Il existe deux approches pour la configuration: une API de promesse simple et une syntaxe d'objet régulière.

Exemple d'implémentation: Matériau angulaire - Dialogues

Tout comme
la source
0

Si vous utilisez ui-router, le bouton Annuler ou Accepter remplace l'URL. Pour éviter cela, vous pouvez retourner false dans chaque cas de la condamnation avec sursis comme ceci:

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
la source
0

Une solution angulaire très simple

Vous pouvez utiliser id avec ou sans message. Sans message, le message par défaut s'affichera.

Directif

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

Manette

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

HTML

Avec un message

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

Sans un message

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

Voici une solution propre et simple en utilisant des promesses angulaires $q, $windowet natif .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
          }
        });
    };
  });

Ici, j'utilise la controllerAssyntaxe et les fonctions fléchées ES6, mais cela fonctionne également dans ES5.

Freezystem
la source
0

Supprimer la fenêtre contextuelle de confirmation à l'aide de bootstrap dans angularjs

très simple .. J'ai une solution pour cela avec l'utilisation du popup de conformation bootstrap. Ici, je suis fourni

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

dans la fenêtre contextuelle du modèle 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');
};

lorsque je clique sur le bouton de suppression, la fenêtre contextuelle de suppression de la conformation de bootstrap s'ouvre et lorsque je clique sur Oui, la ligne de bouton est supprimée.

Rama Krishna
la source
0

ng-click return confirme que 100% fonctionne

dans le fichier html, appelez la fonction delete_plot ()

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

Ajoutez ceci à votre contrôleur

    $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
la source
-1

Je souhaite qu'AngularJS ait une boîte de dialogue de confirmation intégrée. Souvent, il est plus agréable d'avoir une boîte de dialogue personnalisée que d'utiliser le navigateur intégré.

J'ai brièvement utilisé le bootstrap de Twitter jusqu'à ce qu'il soit interrompu avec la version 6. J'ai cherché des alternatives, mais celles que j'ai trouvées étaient compliquées. J'ai décidé d'essayer celui de JQuery UI.

Voici mon exemple que j'appelle lorsque je suis sur le point de supprimer quelque chose 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;
            }
        }
    });

J'espère que ça aidera quelqu'un. Je m'arrachais les cheveux lorsque je devais mettre à niveau ui-bootstrap-tpls.js mais cela a cassé ma boîte de dialogue existante. Je suis entré au travail ce matin, j'ai essayé quelques trucs et j'ai réalisé que je compliquais trop.

Doug Weems
la source