angularjs自定义确认框

时间:2013-06-17 16:02:58

标签: angularjs angularjs-directive

所以我正在尝试使用Angular实现自定义确认框。理想情况下,我只想添加一个属性来启用该功能。例如:

<button type="button" ng-click="delete(foo)">Delete</button>  ->  <button type="button" ng-click="delete(foo)" ng-confirm="Are you sure you want to delete this foo?">Delete</button>

(foo在fooList中的ng-repeat ... foo里面。)

因此,我所遇到的所有问题都围绕着通常发生在不同按钮上的点击事件。我有一个单独的指令“confirmBox”,它将创建我的模态(不使用bootstrap)并处理所有显示/隐藏/等。

我目前使用的是要求我改变我的ng-click功能,我真的想要摆脱它:

当前实施:

<button ... ng-click="confirm('Are you sure you want to delete this foo?, 'delete', foo)">Delete</button>

var confirmModule = angular.module('confirm', []);

confirmModule.run(function($rootScope) {
    $rootScope.confirm = function(text, func, obj) {
        $rootScope.$broadcast('confirm', func, obj, text);
    };
});

confirmModule.directive('confirmBox', function($parse) {

    return {
        restrict: 'A',
        template: myModalTemplate,
        link: function(scope, element, attrs){
            element.hide();
            var noBtn = element.find("[name='no']");
            noBtn.bind("click", function() {
                element.hide();
            });
            scope.$on("confirm", function(event, func, obj, text) {
                var yesBtn = element.find("[name='yes']");
                element.show();
                yesBtn.unbind("click").bind("click", function() {
                    scope[func](obj);
                });
            });
        }
    }
});

有人有什么想法吗?我首先添加了按钮的指令,然后取消绑定click事件,因此ng-click不会触发。然后我留下'delete(foo)'属性中的字符ng-click,我可以用$parse(attrs.ngClick)(scope)执行,但我不知道如何将它与单独的指令按钮点击。

编辑:这是我目前尝试实施的一个小提琴。问题是传递给函数的变量总是未定义的。

http://jsfiddle.net/UCtbj/2/

Edit2:更新了实现,但我并不特别喜欢它如何通过定位其他指令元素将两个指令链接在一起。

http://jsfiddle.net/UCtbj/3/

7 个答案:

答案 0 :(得分:6)

在我看来,你正试图在指令中以jQuery的方式做事。但是,您想要的就像拉入UI-Bootstrap指令以确认操作一样简单。 http://plnkr.co/edit/JhfAF1?p=preview

答案 1 :(得分:3)

模态窗口的第一个简单服务:

app.service('ConfirmService', function($modal) {
  var service = {};
  service.open = function (text, onOk) {
    var modalInstance = $modal.open({
      templateUrl: 'myModalContent.html',
      controller: 'ModalConfirmCtrl',
      resolve: {
        text: function () {
          return text;
        }
      }
    });

    modalInstance.result.then(function (selectedItem) {
      onOk();
    }, function () {
    });
  };

  return service;
})

app.controller('ModalConfirmCtrl', function ($scope, $modalInstance, text) {

  $scope.text = text;

  $scope.ok = function () {
    $modalInstance.close(true);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
});

然后使用它的简单指令:

app.directive('confirm', function(ConfirmService) {
    return {
        restrict: 'A',
        scope: {
            eventHandler: '&ngClick'
        },
        link: function(scope, element, attrs){
          element.unbind("click");
          element.bind("click", function(e) {
            ConfirmService.open(attrs.confirm, scope.eventHandler);
          });
        }
    }
});

你去吧:

<button ng-click="test(12)" confirm='Are you sure?'>Button</button>

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

答案 2 :(得分:1)

允许按钮标记为

<button type="button" ng-click="deleteItem(drink)" ng-confirm="Are you sure you want to delete '{{drink.name}}'">Delete</button>

您可以编写

指令
  • ngClick点击处理程序可以运行
  • 之前截取点击事件
  • 打开一个对话框(使用$modal而不是已删除的$dialog
  • 在对话框的close上(被视为成功)运行元素上ngClick属性指定的函数。

基于the previous answer的代码,您可以执行以下操作:

app.directive('ngConfirm', function($modal, $parse) {
  return {
    // So the link function is run before ngClick's, which has priority 0
    priority: -1,

    link: function(scope, element, attrs) {
      element.on('click', function(e) {
        // Don't run ngClick's handler
        e.stopImmediatePropagation();

        $modal.open({
          templateUrl: 'ng-confirm-template',
          controller: 'ngConfirmController',
          resolve: {
            message: function() {
              return attrs.ngConfirm;
            }
          }
        }).result.then(function() {
          // Pass original click as '$event', just like ngClick
          $parse(attrs.ngClick)(scope, {$event: e});
        });
      });
    }
  };
});

需要一个简单的控制器:

app.controller('ngConfirmController', function($scope, $modalInstance, message) {
  $scope.message = message;

  $scope.yes = function() {
    $modalInstance.close();
  };

  $scope.no = function() {
    $modalInstance.dismiss();
  };
});

和对话框的模板:

<script type="text/ng-template" id="ng-confirm-template">
  <div class="modal-body">
    <p>{{message}}</p>
  </div>
  <div class="modal-footer">
    <button class="btn btn-link pull-left" ng-click="no()">No</button>
    <button class="btn btn-primary pull-right" ng-click="yes()">Yes</button>
  </div>
</script>

您可以在http://plnkr.co/edit/Gm9lFsGb099w6kCMQoVY?p=preview

看到这种情况

编辑:更改了plunker链接到示例,而对话框显示中没有滚动条出现/消失

答案 3 :(得分:1)

这是一个很好的指令。那是ngBootbox。看看吧。

<button class="btn btn-lg btn-primary"
        ng-bootbox-title="A cool title!"
        ng-bootbox-custom-dialog="Some custom text"
        ng-bootbox-buttons="customDialogButtons"
        ng-bootbox-class-name="some-class">
    Custom dialog
</button>

<script>
    $scope.customDialogButtons = {
        warning: {
            label: "Warning!",
            className: "btn-warning",
            callback: function() { $scope.addAction('Warning', false); }
        },
        success: {
            label: "Success!",
            className: "btn-success",
            callback: function() { $scope.addAction('Success!', true) }
        },
        danger: {
            label: "Danger!",
            className: "btn-danger",
            callback: function() { $scope.addAction('Danger!', false) }
        },
        main: {
            label: "Click ME!",
            className: "btn-primary",
            callback: function() { $scope.addAction('Main...!', true) }
        }
    };
    </script>

<强> Demo

<强> ngBootbox

答案 4 :(得分:0)

我为此功能创建了一个repo。它包装ui-bootstrap模式以生成一个确认框。它可以自定义并轻松集成到任何应用程序中。

以下是GitHub的链接:https://github.com/Schlogen/angular-confirm

示例用法:

作为指令:

 <button type="button" ng-click="delete()" confirm-if="checked" confirm="Are you sure, {{name}}?">Delete</button>

作为服务:

$confirm({text: 'Are you sure you want to delete?'})
  .then(function() {
    $scope.deletedConfirm = 'Deleted';
  });

答案 5 :(得分:0)

好的,这是我最终选择的那个

1)为对话框

创建服务
app.service('dialogModal', [
    '$modal', function($modal) {
    return function(message, title, okButton, cancelButton) {

      okButton = okButton === false ? false : (okButton || 'Yes');
      cancelButton = cancelButton === false ? false : (cancelButton || 'No');

      var modalInstance = $modal.open({        
        templateUrl: '/templates/deletePrompt.html',
        controller: ModalInstanceCtrl,
        resolve: {
          settings: function() {
            return {
              modalTitle: title,
              modalBody: message,
              okButton: okButton,
              cancelButton: cancelButton
            };
          }
        }
      });
      // return the modal instance
      return modalInstance;
    }
  }
]);

2)创建一个控制器并在其中传递模型实例

var ModalInstanceCtrl = function ($scope, $modalInstance, settings) {

  angular.extend($scope, settings);

  $scope.ok = function () {
    $modalInstance.close(true);
  };

  $scope.cancel = function () {
    $modalInstance.dismiss('cancel');
  };
};

3)包含标题中的链接以采用默认样式

<link data-require="bootstrap-css@3.x" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />

4)在我自己的CSS中覆盖了样式

5)这是我的删除提示模板

<div id="overlayClearMainDiv" class="dialog-modal">
  <div id="overlayClearText">
    <span>{{modalBody}}</span>
  </div>
  <div id="overlayClearButton">
    <button id="overlayClearYesButton" class="confirmButton" type="button" ng-click="ok()" ng-show="okButton">{{okButton}}</button> 
    <button class="confirmButton-white" ng-click="cancel()" ng-show="cancelButton">{{cancelButton}}</button> 
  </div>
</div>

答案 6 :(得分:0)

这是一个快速的方法 - http://plnkr.co/edit/YklthDZcknmvMjU5A6pe?p=preview

所以基本上如果你有兴趣在用户点击后显示一个模态对话框,那就说一个按钮没有必要让它变得困难。 您所需要的只是一个简单的指令,它封装了ui-bootstrap中的$modal服务。

在我的简单示例中,我只传入表示消息的字符串,然后定义我的指令在用户确认后调用的on-confirm属性。调用函数本身利用$parse的强大功能来解析表达式,一旦解析,就用范围调用它。

很好,很清楚,这就是它的样子。

查看

<body ng-controller="AppController">

    <input type="button" value="Delete" 
           confirm="'Are you sure you want to delete me?'" on-confirm="delete()" />



    <script type="text/ng-template" id="modal.html">
        <div class="modal-header">
            <h3 class="modal-title">Confirm</h3>
        </div>
        <div class="modal-body">
            <p>The world won't be a better place if you delete me.</p>
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" ng-click="ok()">OK</button>
            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
        </div>
    </script>

 </body>

控制人员/指令

angular
    .module('App', ['ui.bootstrap'])
    .controller('AppController', ['$scope', function($scope){
        $scope.delete = function(){
            alert('Woho, Im deleted!');
        };
    }])
    .directive('confirm', ['$modal', '$parse', function($modal, $parse){
        return {
            link: function(scope, el, attr){
              el.bind('click', function(){
                var instance = $modal.open({
                  templateUrl: 'modal.html',
                  controller: ['$scope', '$modalInstance', modalController]
                });

                instance.result.then(function(){
                  // close - action!
                  $parse(attr.onConfirm)(scope);
                },function(){
                  // dimisss - do nothing
                });
              });
            }
        };

        function modalController(modalScope, $modalInstance){
            modalScope.ok = function(){
                modalInstance.close();
            };
            modalScope.cancel = function(){
                modalInstance.dismiss();
            };
        }
    }]);