Диалог подтверждения при нажатии 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

Poiuytrez
источник
Почему в этом случае вы используете терминал? Вроде без него отлично работает (и вы это знаете). Мне просто интересно, почему вы считаете это необходимым в своей директиве.
Саймон Белэнджер
@SimonBelanger Если terminal = false, даже если я нажму «отменить» в диалоговом окне подтверждения, сработает sayHi (). Моя цель - не вызывать sayHi (), если пользователь нажимает кнопку "Отмена".
poiuytrez

Ответы:

92

Если вы не против не использовать ng-click, все работает нормально. Вы можете просто переименовать его во что-нибудь другое и по-прежнему читать атрибут, избегая при этом двойного срабатывания обработчика кликов, проблема, которая существует в данный момент.

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

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

Микель
источник
13
Этот фрагмент кода больше не работает с текущей версией angular. scope. $ eval (..) следует заменить на scope. $ apply (..)
CoolTapes 09
проверьте этот вопрос для диалогового окна подтверждения 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();
          }
        });
      }
    }
  }
]);
Mikeborgh
источник
8
Nb, требуется jQuery
eggonlegs
1
У меня это не работает. Подтверждение не отображается, и щелчок продолжается. Кто-то еще?
OneHoopyFrood
Я думаю, что это плохая идея - сначала не отвязать обработчик щелчка ng-click, а затем полагаться на немедленную остановку и предотвращение дефолта
Джеймс Клих
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
    }
};

Просто .. :)
Но, думаю, настроить нельзя. Он появится с кнопкой «Отменить» или «ОК».

РЕДАКТИРОВАТЬ:

Если вы используете ionic framework, вам нужно использовать диалог 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 вводить принуждение и сравнивать его с истиной.
Лео Лам,
10

Это так просто, используя core javascript + angular js:

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

Если вы нажмете ОК, будет выполнена операция удаления, в противном случае - нет. * 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

Решение только для angular, которое работает параллельно 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>
Scarlz
источник
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;
        }
    }

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

om471987
источник
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-интерфейс обещания и обычный синтаксис объекта.

Пример реализации: Angular Material - Диалоги

Как только
источник
0

Если вы используете ui-router, кнопка отмены или принятия заменяет 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

Очень простое угловое решение

Вы можете использовать id с сообщением или без него. Без сообщения будет отображаться сообщение по умолчанию.

Директива

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.

Freezystem
источник
0

Удалить всплывающее окно подтверждения с помощью начальной загрузки в angularjs

очень просто .. У меня есть одно решение с использованием всплывающего окна с подтверждением начальной загрузки. Здесь мне предоставлено

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

во всплывающем окне модели начальной загрузки:

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

когда я нажимаю кнопку удаления, откроется всплывающее окно с подтверждением удаления, а когда я нажму кнопку «Да», строка будет удалена.

Рама Кришна
источник
0

ng-click return подтверждаю 100% работает

в html файле вызовите функцию delete_plot ()

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

Добавьте это в свой контроллер

    $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

Я бы хотел, чтобы у AngularJS был встроенный диалог подтверждения. Часто лучше иметь настраиваемый диалог, чем использовать встроенный в браузер.

Я ненадолго использовал загрузочную программу twitter, пока она не была прекращена в версии 6. Я поискал альтернативы, но те, которые я нашел, были сложными. Я решил попробовать JQuery UI.

Вот мой образец, который я вызываю, когда собираюсь удалить что-то из 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, но это нарушило мой существующий диалог. Я пришел на работу сегодня утром, попробовал несколько вещей и потом понял, что слишком усложняю.

Дуг Уимс
источник