【问题标题】:Intercepting ng-click in angularJS在 angularJS 中拦截 ng-click
【发布时间】:2013-04-25 07:34:28
【问题描述】:

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

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

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

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

谢谢

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    我已将示例指令放入:

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

    希望对您有所帮助。

    【讨论】:

    • 这也很接近我的做法。但是,这是另一个工作原理几乎相同的 plunk,除了它不关心您是否有 ng-click ..plnkr.co/edit/Cwu15Z8U6ok0MMF8p6Ks?p=preview
    • @ganaraj:当我单击取消时,这不起作用,因为 JQLite 的 createEventHandler 继续遍历所有绑定的事件,并且不会阻止第二个 bind('click',...) 被调用。 (我的浏览器:Mac OSX 10.6.8 上的 Chrome 版本 26.0.1410.65)
    • 这也阻止了所有其他指令的工作,即如果你添加一个 ng-show 到同一个标签......
    • @samson 同意 - 优雅的解决方案,但会产生其他问题。我最终使用了一个带有自定义“&”绑定的隔离范围。
    • @georgiosd 我已经在下面发布了我的方法,它与这个类似,但(我认为)要简单得多。
    【解决方案2】:

    我已经放弃让 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 的实现方式来改进这一点,但我还没有开始!

    【讨论】:

    • 还需要 $apply($eval()) 吗?似乎只需 $apply(action) 就可以正常工作。
    • 嗯...自从我写这篇文章以来已经有一段时间了...我想您不需要两者!
    【解决方案3】:

    我玩了很长时间,但是 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/23718694/1135826

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

      • 谢谢,@tosh!这使我走上了我需要做的正确轨道。我在下面发布了另一个答案,它采用相同的概念,但将它与指令相结合,因此我可以自定义我的确认对话框。
      猜你喜欢
      • 1970-01-01
      • 2016-10-28
      • 2023-03-31
      • 2015-05-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多