Діалогове вікно підтвердження при натисканні клавіші ng - AngularJS


85

Я намагаюся встановити діалогове вікно підтвердження за ng-clickдопомогою користувацької директиви 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)
                    }
                });
            }
        };
}])

Це чудово працює, але, на жаль, вирази всередині тегу за допомогою моєї директиви не обчислюються:

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

(ім'я не оцінюється в цьому випадку). Здається, це пов’язано з параметром терміналу моєї директиви. Чи маєте ви ідеї обхідного шляху?

Щоб протестувати мій код: http://plnkr.co/edit/EHmRpfwsgSfEFVMgRLgj?p=preview


Чому ви використовуєте термінал у цьому випадку? Здається, це чудово працює і без (і ви це знаєте). Мені просто цікаво, чому ви вважаєте це необхідним у своїй директиві.
Саймон Белангер

@SimonBelanger При терміналі = false, навіть якщо я натисну на "скасувати" у діалоговому вікні підтвердження, запускається sayHi (). Моя мета - не зателефонувати sayHi (), якщо користувач натискає кнопку скасувати.
poiuytrez

Відповіді:


92

Якщо ви не проти не використовувати ng-click, це працює нормально. Ви можете просто перейменувати його на щось інше і все одно прочитати атрибут, уникаючи при цьому обробника клацань, який запускається двічі, що існує на даний момент.

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

Я думаю, що проблема полягає в тому, що terminalінші директиви не запускаються. Прив'язка даних за допомогою {{ }}просто є псевдонімом для ng-bindдирективи, яку, імовірно, скасовує terminal.


13
Цей фрагмент коду більше не працює з поточною версією angular. Область. $ eval (..) слід замінити на область. $ apply (..)
CoolTapes

будь ласка , перевірте це питання для діалогу підтвердження JS з E2e-тести stackoverflow.com/questions/16424961 / ...
ndequeker

Це працює, але що станеться, якщо я поставлю прапорець біля chrome "Уникати цієї сторінки, щоб створювати додаткові діалоги"? : s
bigpony

58

Чистий директивний підхід.

Оновлення: стара відповідь (2014)

В основному він перехоплює ng-clickподію, відображає повідомлення, що міститься в ng-confirm-click="message"директиві, і просить користувача підтвердити. Якщо натиснути кнопку підтвердження, нормальний ng-clickфайл виконується, якщо сценарій не завершується і ng-clickне запускається.

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

Код кредиту Зак Сноу: http://zachsnow.com/#!/blog/2013/confirming-ng-click/

Оновлення: Нова відповідь (2016)

1) Змінено префікс з 'ng' на 'mw', оскільки попередній ('ng') зарезервований для власних кутових директив.

2) Модифікована директива для передачі функції та повідомлення замість перехоплення події ng-click.

3) Додано за замовчуванням "Ви впевнені?" повідомлення у випадку, якщо спеціальне повідомлення не надається для 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, потрібен jQuery
eggonlegs

1
Це не працює для мене. Немає підтвердження, і натискання продовжується. Будь-хто інший?
OneHoopyFrood

Я думаю, що це погана ідея, якщо спочатку не розв’язати обробник клацання клацніть нг, а потім покладатися на негайну зупинку та запобігти замовчуванню
James Kleeh

OneHoopyFrood, у вас повинна бути дійсна функція в ng-click = "", інакше вона не вдається. Дякую.
mikeborgh

Чому крок 2) Модифікована директива для передачі функції та повідомлення замість перехоплення події ng-click?
Silver

46

Для мене, https://www.w3schools.com/js/js_popup.asp , діалогове вікно підтвердження за замовчуванням браузера спрацювало дуже багато. просто спробував це:

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

Просто .. :)
Але я думаю, ви не можете налаштувати його. З'явиться кнопка "Скасувати" або "Добре".

РЕДАГУВАТИ:

Якщо ви використовуєте іонний фреймворк, вам потрібно використовувати діалогове вікно ionicPopup, як у:

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

Детальніше див .: $ ionicPopup


Це справді виглядає чисто, проте, я думаю, це суперечить декларативному підходу в Angular. За допомогою цього підходу легко помістити логіку перегляду всередину контролера. Якщо це можливо, корисно тримати контролер у чистоті від елементів інтерфейсу.
Джим Ахо

1
Ви можете позбутися від == true, що в цьому випадку є абсолютно непотрібним, оскільки confirm()вже повертає логічне значення. Не потрібно змушувати JS вводити примусово і порівнювати з true.
Лео Лам,

10

Це настільки просто за допомогою основного javascript + angular js:

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

Якщо натиснути OK, тоді буде виконана операція видалення, інакше ні. * id - параметр, запис, який потрібно видалити.


5

Ви не хочете використовувати, terminal: falseоскільки саме це блокує обробку всередині кнопки. Натомість у своєму linkочистіте, attr.ngClickщоб запобігти поведінці за замовчуванням.

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

Працює у версії Angular, на яку ви посилаєтесь у plunker, але якщо ви посилаєтесь на ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js, це не працює належним чином.
ChrisW

Зрештою, запропонований мною підхід працює лише у деяких випадках, оскільки ngClick робить більше, ніж просто прив'язку до 'click'. Я думаю, що більш правильний підхід - мати справу з підтвердженням у обробнику ng-click, а не за допомогою окремого атрибута.
Степан Ріга

4

На сьогоднішній день це рішення працює для мене:

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

Подяки: https://gist.github.com/asafge/7430497#file-ng-really-js



4

Рішення лише для кутів, яке працює поряд ng-click, можливо за допомогою компіляції для обтікання ng-clickвиразу.

Директива:

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

Кодекс говорить все


1

Зразок коду HTML 5

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

Зразок коду користувальницької директиви 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

Діалогове вікно підтвердження може бути реалізоване за допомогою AngularJS Material :

$ mdDialog відкриває діалогове вікно програми, щоб інформувати користувачів про важливу інформацію або вимагати від них прийняття рішень. Існує два підходи до налаштування: простий API обіцянки та звичайний синтаксис об’єкта.

Приклад реалізації: Кутовий матеріал - Діалоги


0

Якщо ви використовуєте користувальницький інтерфейс, кнопка скасування або прийняття замінює URL-адресу. Щоб запобігти цьому, ви можете повернути false у кожному випадку умовного речення, наприклад:

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

Дуже просте кутове рішення

Ви можете використовувати ідентифікатор із повідомленням або без нього. Без повідомлення відображатиметься повідомлення за замовчуванням.

Директива

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

Контролер

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

HTML

З повідомленням

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

Без повідомлення

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

0

Ось чисте і просте рішення , використовуючи кутові обіцянки $q, $windowі рідну .confirm()модальність:

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

Тут я використовую controllerAsсинтаксис та функції стрілок ES6, але він також працює у звичайній старій ES5.


0

Видаліть спливаюче вікно підтвердження, використовуючи bootstrap у angularjs

дуже просто .. У мене є одне рішення для цього за допомогою спливаючого вікна конформації bootstrap. Тут я забезпечений

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

у спливаючому вікні моделі 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');
};

при натисканні кнопки видалення відкриється спливаюче вікно видалення конформації, а при натисканні рядок кнопки так буде видалено.



-1

Я хотів би, щоб AngularJS мав вбудований діалог підтвердження. Часто приємніше мати налаштоване діалогове вікно, ніж використання вбудованого.

Я коротко використовував завантажувальний ремінь Twitter, доки його не припинили з версією 6. Я шукав альтернативи, але ті, які я знайшов, були складними. Я вирішив спробувати інтерфейс JQuery.

Ось мій зразок, до якого я телефоную, коли збираюся щось видалити з 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;
            }
        }
    });

Сподіваюся, це комусь допомагає. Я виривав волосся, коли мені потрібно було оновити ui-bootstrap-tpls.js, але це зламало моє існуюче діалогове вікно. Я прийшов на роботу сьогодні вранці, спробував кілька речей, а потім зрозумів, що переставав ускладнювати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.