Finestra di dialogo di conferma su ng-click - AngularJS


85

Sto cercando di impostare una finestra di dialogo di conferma su un ng-clickutilizzo di una direttiva angularjs personalizzata:

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

Funziona benissimo ma sfortunatamente, le espressioni all'interno del tag che utilizzano la mia direttiva non vengono valutate:

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

(il nome non viene valutato in questo caso). Sembra essere dovuto al parametro terminale della mia direttiva. Hai qualche idea di soluzione alternativa?

Per testare il mio codice: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview


Perché usi il terminale in questo caso? Sembra che funzioni perfettamente senza (e tu lo sai). Mi chiedo solo perché pensi che sia necessario nella tua direttiva.
Simon Belanger

@SimonBelanger Con terminal = false, anche se clicco su "annulla" nella finestra di dialogo di conferma, viene attivato sayHi (). Il mio obiettivo non è chiamare sayHi () se l'utente fa clic su Annulla.
poiuytrez

Risposte:


92

Se non ti dispiace non usarlo ng-click, funziona bene. Puoi semplicemente rinominarlo in qualcos'altro e leggere ancora l'attributo, evitando che il gestore dei clic venga attivato due volte, problema che c'è al momento.

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

Penso che il problema sia terminalistruire altre direttive a non funzionare. Il data-binding con {{ }}è solo un alias per la ng-binddirettiva, che è presumibilmente annullato da terminal.


13
Questo frammento di codice non funziona più con la versione corrente di angular. scope. $ eval (..) dovrebbe essere sostituito con scope. $ apply (..)
CoolTapes,

si prega di controllare questa domanda per una finestra di conferma con JS E2E-test stackoverflow.com/questions/16424961/...
ndequeker

Funziona, ma cosa succede se seleziono la casella di controllo di Chrome "Evita questa pagina per creare finestre di dialogo aggiuntive"? : s
bigpony

58

Un approccio direttiva pulito.

Aggiornamento: vecchia risposta (2014)

Fondamentalmente intercetta l' ng-clickevento, visualizza il messaggio contenuto nella ng-confirm-click="message"direttiva e chiede all'utente di confermare. Se si fa clic su conferma, viene ng-clickeseguita la normale esecuzione, in caso contrario lo script termina e ng-clicknon viene eseguito.

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

Credito in codice a Zach Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Aggiornamento: nuova risposta (2016)

1) Prefisso modificato da 'ng' a 'mw' poiché il primo ('ng') è riservato alle direttive angolari native.

2) Direttiva modificata per passare una funzione e un messaggio invece di intercettare l'evento ng-click.

3) Aggiunto predefinito "Sei sicuro?" messaggio nel caso in cui non venga fornito un messaggio personalizzato 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();
          }
        });
      }
    }
  }
]);

8
Nb, richiede jQuery
eggonlegs

1
Questo non funziona per me. Non viene visualizzato alcun messaggio di conferma e il clic continua. Chiunque altro?
OneHoopyFrood

Penso che sia una cattiva idea non svincolare prima il gestore dei clic ng-click e poi fare affidamento su stop immediate e prevent default
James Kleeh

OneHoopyFrood, devi avere una funzione valida in ng-click = "" altrimenti fallisce. Grazie.
mikeborgh

Perché passaggio 2) Direttiva modificata per passare una funzione e un messaggio invece di intercettare l'evento ng-click?
Argento

46

Per me, https://www.w3schools.com/js/js_popup.asp , la finestra di dialogo di conferma predefinita del browser ha funzionato molto. ho appena provato questo:

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

Semplice .. :)
Ma penso che non puoi personalizzarlo. Apparirà con il pulsante "Annulla" o "Ok".

MODIFICARE:

Se stai usando ionic framework, devi usare la finestra di dialogo ionicPopup come 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
     }
   });
 };

Per maggiori dettagli, fare riferimento a: $ ionicPopup


Sembra davvero pulito, tuttavia penso che sia contro l'approccio dichiarativo in Angular. È facile inserire la logica di visualizzazione all'interno del controller con questo approccio. Se possibile, può essere utile mantenere il controller pulito dagli elementi dell'interfaccia utente.
Jim Aho

1
Puoi sbarazzarti di == true, che è completamente inutile in questo caso, perché confirm()restituisce già un valore booleano. Non è necessario che JS digiti costringilo e confrontalo con true.
Léo Lam

10

È così semplice usare il core javascript + angular js:

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

Se si fa clic su OK, verrà eseguita l'operazione di eliminazione, altrimenti no. * id è il parametro, record che vuoi eliminare.


5

Non si desidera utilizzare terminal: falsepoiché è ciò che blocca l'elaborazione all'interno del pulsante. Invece, nel tuo linkchiaro il attr.ngClickper impedire il comportamento predefinito.

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

Funziona nella versione di Angular a cui fai riferimento in plunker, ma se fai riferimento a ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js non funziona come previsto.
ChrisW

In definitiva, il mio approccio suggerito funziona solo per alcuni casi, perché ngClick fa molto di più del semplice collegamento a "clic". Penso che l'approccio più corretto sia gestire la conferma nel gestore di ng-click piuttosto che tramite un attributo separato.
Stepan Riha

4

Nella data odierna questa soluzione funziona per me:

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

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



4

Una soluzione solo angolare che funziona insieme ng-clickè possibile utilizzando compile per racchiudere l' ng-clickespressione.

Direttiva:

.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>

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

Il codice dice tutto


1

Esempio di codice HTML 5

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

Esempio di codice della direttiva personalizzata 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();
       });
     }
    };
});

1

La finestra di dialogo di conferma può essere implementata utilizzando AngularJS Material :

$ mdDialog apre una finestra di dialogo sull'app per informare gli utenti sulle informazioni critiche o richiedere loro di prendere decisioni. Esistono due approcci per l'installazione: una semplice API Promise e la sintassi degli oggetti regolare.

Esempio di implementazione: Angular Material - Dialogs


0

Se utilizzi ui-router, il pulsante Annulla o accetta sostituisce l'URL. Per evitare ciò puoi restituire false in ogni caso della frase condizionale come questa:

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

0

Una soluzione angolare molto semplice

Puoi usare id con un messaggio o senza. Senza messaggio verrà visualizzato il messaggio predefinito.

Direttiva

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

Controller

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

HTML

Con un messaggio

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

Senza un messaggio

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

0

Ecco una soluzione semplice e pulito con promesse angolari $q, $windowe nativo .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
          }
        });
    };
  });

Qui sto usando la controllerAssintassi e le funzioni freccia ES6, ma funziona anche in ES5 semplice.


0

Elimina il popup di conferma utilizzando bootstrap in angularjs

molto semplice .. Ho una soluzione per questo con l'utilizzo di popup di conformazione bootstrap. Eccomi qui

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

nel popup del modello 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 faccio clic sul pulsante di eliminazione, si aprirà il popup di eliminazione della conformazione del bootstrap e quando clicco su sì la riga del pulsante verrà eliminata.


0

ng-click return conferma che il 100% funziona

nel file html chiama la funzione delete_plot ()

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

Aggiungilo al tuo controller

    $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")

        }
    }

-1

Vorrei che AngularJS avesse una finestra di dialogo di conferma incorporata. Spesso, è più bello avere una finestra di dialogo personalizzata che utilizzare quella del browser incorporata.

Ho usato brevemente il bootstrap di Twitter fino a quando non è stato interrotto con la versione 6. Ho cercato delle alternative, ma quelle che ho trovato erano complicate. Ho deciso di provare l'interfaccia utente di JQuery.

Ecco il mio esempio che chiamo quando sto per rimuovere qualcosa da 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;
            }
        }
    });

Spero che questo aiuti qualcuno. Mi stavo strappando i capelli quando avevo bisogno di aggiornare ui-bootstrap-tpls.js ma ha rotto la mia finestra di dialogo esistente. Sono entrato al lavoro questa mattina, ho provato alcune cose e poi ho capito che stavo complicando troppo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.