21

是否可以为 ng-click 编写拦截器?我有一个按钮或链接会导致在后端删除一个对象。我想通过向按钮/链接添加一个属性来获得一个确认对话框(模式)。例如:

<a href="#" ng-click="deleteIt(id)" confirmation-needed>Delete</a>

AngularJS可以做到这一点吗?有没有更好的方法来解决这个问题?

编辑deleteIt 方法驻留在不同的控制器中。

谢谢

4

4 回答 4

51

我在以下位置放置了一个示例指令:

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

我通过创建一个指令来实现它:

  1. 有一个高于priorityngClick以便它在之前被调用ngClick
  2. 使它terminal不会调用ngClick.
  3. 侦听点击事件,然后ngClick在消息正常时评估值。

作为奖励,您可以传递自己的消息,例如:

<a href="#" ng-click="deleteIt(id)" 
    confirmation-needed="Really Delete?"
        >Delete with custom message</a>

代码如下所示:

app.directive('confirmationNeeded', function () {
  return {
    priority: 1,
    terminal: true,
    link: function (scope, element, attr) {
      var msg = attr.confirmationNeeded || "Are you sure?";
      var clickAction = attr.ngClick;
      element.bind('click',function () {
        if ( window.confirm(msg) ) {
          scope.$eval(clickAction)
        }
      });
    }
  };
});

希望有帮助。

于 2013-04-25T09:27:04.303 回答
10

我已经放弃让 Piran 的答案按照我的意愿工作。相反,我已经开始用我自己的指令替换 ngClick:

.directive('confirmClick', function() {
    return {
        restrict: 'A',
        link: function(scope, elt, attrs) {
            elt.bind('click', function(e) {
                var message = attrs.confirmation || "Are you sure you want to do that?";
                if (window.confirm(message)) {
                    var action = attrs.confirmClick;
                    if (action)
                        scope.$apply(scope.$eval(action));
                }
            });
        },
    };
})

该指令甚至没有自己的范围,这大大简化了它与其他指令的组合。它直接从attrs. 它是这样使用的:

<span ng-show="editing" confirm-click="delete()" confirmation="delete confirmation message goes here">some text</span>

该函数必须存在于链delete()中更高的某个位置。$scope我相信这可以通过仔细研究如何ng-click实现来改进,但我还没有开始!

于 2013-09-13T19:05:31.683 回答
5

我玩了很长时间,但是 Angular 的异步特性使得很难指望每个指令都能很好地协同工作。然后,我看到了@tosh 的回答,这让我开始思考。

我认为这结合了几个优点:创建指令和前置 ngClick

因此,只需将此指令添加到您的应用程序中,然后将“confirm-click”属性添加到您的链接中,并将 confirmClick() 函数添加到您的 ngClick 中。

关联:

<a href="#" ng-click="confirmClick() && deleteIt(id)" confirm-click>Delete</a>

指示:

.directive('confirmClick', function() {
    return {
        link: function (scope, element, attrs) {
            // setup a confirmation action on the scope
            scope.confirmClick = function(msg) {
                // msg can be passed directly to confirmClick('are you sure?') in ng-click
                // or through the confirm-click attribute on the <a confirm-click="Are you sure?"></a>
                msg = msg || attrs.confirmClick || 'Are you sure?';
                // return true/false to continue/stop the ng-click
                return confirm(msg);
            }
        }
    }
})

这与注入标准的 confirm() 对话框非常相似,但是因为您在指令中拥有它,所以您可以自定义选择运行确认对话框的方式(可能是一个漂亮的模式,而不是窗口对话框)。

**** 奖励答案 ****

我对此进行了更多尝试,并集成了一个使用模式窗口作为确认的解决方案,而不是默认窗口。这是完整的解决方案:https ://stackoverflow.com/a/237186​​94/1135826

于 2014-05-17T04:14:38.770 回答
3

您可以注入$window您的控制器,以便您可以$window.confirm从您的范围内使用,然后:

<a href="#" ng-click="confirm('message') && deleteIt(id)">Delete</a>
于 2013-04-25T08:20:52.043 回答