Okno dialogowe potwierdzenia na ng-click - AngularJS

85

Próbuję ustawić okno dialogowe potwierdzenia na ng-clickpodstawie niestandardowej dyrektywy angularjs:

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

Działa to świetnie, ale niestety wyrażenia wewnątrz tagu używające dyrektywy my nie są oceniane:

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

(nazwa nie jest oceniana w tym przypadku). Wydaje się, że jest to spowodowane parametrem terminalowym mojej dyrektywy. Czy masz jakieś pomysły na obejście tego problemu?

Aby przetestować mój kod: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview

poiuytrez
źródło
Dlaczego w tym przypadku używasz terminala? Wygląda na to, że działa idealnie bez (i wiesz o tym). Zastanawiam się tylko, dlaczego uważasz, że jest to konieczne w twojej dyrektywie.
Simon Belanger,
@SimonBelanger Z terminal = false, nawet jeśli kliknę „anuluj” w oknie dialogowym potwierdzenia, wyzwalana jest funkcja sayHi (). Moim celem nie jest wywoływanie funkcji sayHi (), jeśli użytkownik kliknie przycisk Anuluj.
poiuytrez

Odpowiedzi:

92

Jeśli nie masz nic przeciwko nieużywaniu ng-click, działa OK. Możesz po prostu zmienić jego nazwę na inną i nadal odczytywać atrybut, unikając jednocześnie dwukrotnego wyzwalania modułu obsługi kliknięcia. Problem jest w tej chwili.

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

Myślę, że problem polega na tym, że terminalinne dyrektywy nie działają. Powiązanie danych z {{ }}jest tylko aliasem ng-binddyrektywy, która prawdopodobnie została anulowana przez terminal.

mikel
źródło
13
Ten fragment kodu nie działa już z bieżącą wersją angular. zakres. $ eval (..) należy zastąpić zakresem. $ apply (..)
CoolTapes
proszę sprawdzić to pytanie, aby wyświetlić okno dialogowe potwierdzenia JS z E2E-tests stackoverflow.com/questions/16424961/ ...
ndequeker
To działa, ale co się stanie, jeśli zaznaczę pole wyboru „Unikaj tej strony, aby tworzyć dodatkowe okna dialogowe”? : s
bigpony
58

Podejście oparte na czystych dyrektywach.

Aktualizacja: Stara odpowiedź (2014)

W zasadzie przechwytuje ng-clickzdarzenie, wyświetla komunikat zawarty w ng-confirm-click="message"dyrektywie i prosi użytkownika o potwierdzenie. Jeśli klikniesz przycisk potwierdzenia, wykonywane jest normalne działanie ng-click, jeśli nie, skrypt kończy działanie i ng-clicknie jest uruchamiany.

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

Kod kredytowy dla Zacha Snow: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Aktualizacja: Nowa odpowiedź (2016)

1) Zmieniono przedrostek z „ng” na „mw”, ponieważ poprzedni („ng”) jest zarezerwowany dla natywnych dyrektyw kątowych.

2) Zmodyfikowana dyrektywa do przekazywania funkcji i komunikatu zamiast przechwytywania zdarzenia ng-click.

3) Dodano domyślne „Czy na pewno?” komunikat w przypadku, gdy niestandardowa wiadomość nie zostanie dostarczona do 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
źródło
8
Uwaga
1
To nie działa na mnie. Brak potwierdzenia, a kliknięcie trwa. Ktoś jeszcze?
OneHoopyFrood
Myślę, że to zły pomysł, aby najpierw nie odpinać programu obsługi kliknięć ng-click, a następnie polegać na natychmiastowym zatrzymaniu i zapobieganiu domyślnemu
James Kleeh
OneHoopyFrood, musisz mieć prawidłową funkcję w ng-click = "", bo inaczej się nie powiedzie. Dzięki.
mikeborgh
Dlaczego krok 2) Zmodyfikowana dyrektywa do przekazywania funkcji i komunikatu zamiast przechwytywania zdarzenia ng-click?
Srebro
46

Dla mnie https://www.w3schools.com/js/js_popup.asp , domyślne okno dialogowe potwierdzenia w przeglądarce działało bardzo dużo. właśnie wypróbowałem to:

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

Proste… :)
Ale myślę, że nie da się go dostosować. Pojawi się z przyciskiem „Anuluj” lub „OK”.

EDYTOWAĆ:

W przypadku korzystania z platformy jonowej należy użyć okna dialogowego ionicPopup, jak w:

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

Aby uzyskać więcej informacji, zobacz: $ ionicPopup

Kailas
źródło
Rzeczywiście wygląda na czysty, ale myślę, że jest to sprzeczne z deklaratywnym podejściem w Angular. Dzięki takiemu podejściu można łatwo umieścić logikę widoku wewnątrz kontrolera. Jeśli to możliwe, pomocne może być utrzymanie kontrolera w czystości od elementów interfejsu użytkownika.
Jim Aho
1
Możesz się pozbyć funkcji == true, która w tym przypadku jest zupełnie niepotrzebna, ponieważ confirm()już zwraca wartość logiczną. Nie ma potrzeby, aby JS wprowadzał wymuszenie tego i porównywał z prawdą.
Léo Lam
10

To takie proste przy użyciu rdzenia javascript + angular js:

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

Jeśli klikniesz OK, operacja usuwania zajmie, w przeciwnym razie nie. * id to parametr, rekord, który chcesz usunąć.

VBMali
źródło
5

Nie chcesz używać, terminal: falseponieważ to właśnie blokuje przetwarzanie wewnątrz przycisku. Zamiast tego linkusuń zaznaczenie, attr.ngClickaby zapobiec domyślnemu zachowaniu.

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
źródło
Działa w wersji Angulara, do której odwołujesz się w plunkerze, ale jeśli odwołujesz się do ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js, nie działa zgodnie z oczekiwaniami.
ChrisW
Ostatecznie moje sugerowane podejście działa tylko w niektórych przypadkach, ponieważ ngClick robi o wiele więcej niż proste powiązanie z „kliknięciem”. Myślę, że bardziej poprawnym podejściem jest zajęcie się potwierdzeniem w module obsługi ng-click, a nie poprzez oddzielny atrybut.
Stepan Riha,
4

W dzisiejszym dniu to rozwiązanie działa u mnie:

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

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

Nanu
źródło
4

Rozwiązanie tylko kątowe, które działa równolegle, ng-clickjest możliwe przy użyciu kompilacji do zawijania ng-clickwyrażenia.

Dyrektywa:

.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
źródło
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;
        }
    }

Kod mówi wszystko

om471987
źródło
1

Przykład kodu HTML 5

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

Przykładowy kod według dyrektywy niestandardowej 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
źródło
1

Okno dialogowe potwierdzenia można zaimplementować za pomocą AngularJS Material :

$ mdDialog otwiera okno dialogowe nad aplikacją, aby poinformować użytkowników o krytycznych informacjach lub zażądać od nich podjęcia decyzji. Istnieją dwa podejścia do konfiguracji: prosty interfejs API obietnicy i zwykła składnia obiektów.

Przykład implementacji: Angular Material - Dialogs

Tak jak
źródło
0

Jeśli używasz ui-router, przycisk anulowania lub akceptacji zastępuje adres URL. Aby temu zapobiec, możesz zwrócić fałsz w każdym przypadku warunkowego zdania w następujący sposób:

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
źródło
0

Bardzo proste rozwiązanie kątowe

Możesz użyć id z wiadomością lub bez. Bez wiadomości pojawi się domyślny komunikat.

Dyrektywa

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

Kontroler

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

HTML

Z przesłaniem

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

Bez wiadomości

<span ng-click="sayHello()" ng-confirm-message>Say Hello!</span>
Merlinie
źródło
0

Tu jest czyste i proste rozwiązanie za pomocą kątowych obietnic $q, $windoworaz natywną .confirm()modalne:

angular.module('myApp',[])
  .controller('classicController', ( $q, $window ) => {
    this.deleteStuff = ( id ) => {
      $q.when($window.confirm('Are you sure ?'))
        .then(( confirm ) => {
          if ( confirm ) {
            // delete stuff
          }
        });
    };
  });

Tutaj używam funkcji controllerAsskładni i strzałek ES6, ale działa to również w zwykłym starym ES5.

Freezystem
źródło
0

Usuń wyskakujące okienko potwierdzenia za pomocą bootstrap w angularjs

bardzo proste .. Mam jedno rozwiązanie tego problemu z użyciem wyskakującego okienka konformacji bootstrap. Tutaj jestem zapewniony

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

w wyskakującym okienku modelu 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');
};

kiedy kliknę przycisk usuwania bootstrap, otworzy się wyskakujące okienko potwierdzenia, a kiedy kliknę przycisk tak, wiersz przycisku zostanie usunięty.

Rama Krishna
źródło
0

ng-click return potwierdź 100% działa

w pliku html wywołaj funkcję delete_plot ()

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

Dodaj to do swojego kontrolera

    $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
źródło
-1

Chciałbym, żeby AngularJS miał wbudowane okno dialogowe potwierdzenia. Często lepiej jest mieć dostosowane okno dialogowe niż korzystanie z wbudowanej przeglądarki.

Krótko korzystałem z Twittera, dopóki nie został wycofany z wersją 6. Rozejrzałem się za alternatywami, ale te, które znalazłem, były skomplikowane. Zdecydowałem się wypróbować interfejs JQuery UI.

Oto moja próbka, którą dzwonię, kiedy mam zamiar usunąć coś z 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;
            }
        }
    });

Mam nadzieję, że to komuś pomoże. Wyciągałem włosy, gdy musiałem zaktualizować ui-bootstrap-tpls.js, ale zepsuło to moje istniejące okno dialogowe. Przyszedłem dziś rano do pracy, spróbowałem kilku rzeczy i zdałem sobie sprawę, że zbytnio komplikuję.

Doug Weems
źródło