Intercepting ng-click in angularJS

前端 未结 4 1318
一生所求
一生所求 2020-12-05 05:17

is it possible to write an interceptor for ng-click? I have a button or a link that leads to a deletion of an object in the backend. I\'d like to have a confirmation dialog

相关标签:
4条回答
  • 2020-12-05 05:43

    I played with this for a long time, but the async nature of Angular makes it tough to count on every directive playing nicely together. Then, I saw @tosh's answer, which got me thinking.

    I think this combines several advantages: Create a Directive and Prepend ngClick

    So, just add this directive to your app, and then add the "confirm-click" attribute to your link, as well as the confirmClick() function to your ngClick.

    Link:

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

    Directive:

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

    This is very similar to injecting the standard confirm() dialog, but because you have it in a directive, you can customize how you choose to run your confirm dialog (maybe a pretty modal, instead of a window dialog).

    **** BONUS ANSWER ****

    I played with this more and integrated a solution that uses a modal window as the confirmation, rather than the default window. Here's the complete solution: https://stackoverflow.com/a/23718694/1135826

    0 讨论(0)
  • 2020-12-05 05:46

    I've put an example directive in:

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

    I achieve it by creating a directive:

    1. with a higher priority than ngClick, so that it gets called before ngClick,
    2. making that terminal so that it doesn't call ngClick.
    3. listening to click events, and then evaluating the ngClick value if the message is ok.

    As a bonus, you can pass in your own message, such as:

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

    The code looks like this:

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

    Hope that helps.

    0 讨论(0)
  • 2020-12-05 05:55

    I've given up on getting Piran's answer to work as I'd like it to. Instead, I've started just replacing ngClick with my own directive:

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

    This directive doesn't even have its own scope, which simplifies combining it with other directives significantly. It takes everything it needs directly from the attrs. It's used like so:

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

    The delete() function must exist somewhere higher up in the $scope chain. I'm sure this could be improved by taking a closer look at how ng-click is implemented, but I haven't gotten around to it yet!

    0 讨论(0)
  • 2020-12-05 05:55

    You can inject $window into your controller so that you can use $window.confirm from your scope, then:

    <a href="#" ng-click="confirm('message') && deleteIt(id)">Delete</a>
    
    0 讨论(0)
提交回复
热议问题