8

所以我正在尝试使用 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 在 ng-repeat... fooList 中的 foo..)

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

我目前使用的要求我改变我的 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);
                });
            });
        }
    }
});

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

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

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

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

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

4

7 回答 7

7

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

于 2013-06-17T20:53:17.103 回答
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

于 2015-02-03T17:51:46.140 回答
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>

演示

ngBootbox

于 2015-04-13T13:27:49.580 回答
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元素上的属性指定的函数。

基于上一个答案的代码,您可以按如下方式执行此操作:

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 链接更改为示例,而在对话框显示中没有出现/消失的滚动条

于 2015-02-01T10:36:09.387 回答
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>
于 2015-02-03T14:39:24.093 回答
0

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

因此,基本上,如果您有兴趣在用户单击时显示模态对话框,比如说,一个按钮,就没有必要让它变得困难。您只需要一个简单的指令来封装$modalui-bootstrap 中的服务。

在我的简单示例中,我只传入一个表示消息的字符串,然后定义一个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();
            };
        }
    }]);
于 2015-02-04T20:20:47.657 回答
0

我为此功能创建了一个仓库。它包装了 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';
  });
于 2015-02-02T21:39:22.613 回答