【问题标题】:Custom delete confirm in angularJSangularJS中的自定义删除确认
【发布时间】:2014-05-19 20:22:18
【问题描述】:

我有一个带有项目列表的 Angular 应用程序。我试图实现一个自定义的“确认删除”模式,以便当用户单击项目旁边的“删除”按钮时,模式打开以确认删除。单击“是”时,将触发 deleteItem() 函数。我的问题是服务器返回 404 not found 删除请求。当我使用标准的 jquery 确认对话框时它可以工作,所以我猜测项目 ID 没有通过模态传递到删除函数。谁能帮忙?

   <div class="span6">
        <table class="table table-striped table-condensed">
            <thead>
            <tr>
                <th style="min-width: 80px;">Name:</th>
                <th style="width:20px;"> </th>
                <th style="width:20px;"> </th>
            </tr>
            </thead>
            <tbody>
            <tr ng-repeat="item in items | filter:query | orderBy:orderProp">
                <td>{{ item.name }}</td>


                <td><a ng-click="editItem(item.id)" class="btn btn-small btn-primary">Edit</a></td>
                <td><a ng-click="openModal(item.id)" class="btn btn-small btn-success">Delete</a></td>

            </tr>
            </tbody>
        </table>

          <modal-dialog show='modalShown' id = "itemModal" width='300px' height='40%'>
                  <p>Are you sure you want to delete this item?<p>
                      <button ng-click = "deleteItem(item.id)" class = "link">Yes</button>
          </modal-dialog>

    </div>

这是控制器:

angular.module('myApp.controllers')
    .controller('ItemCtrl', ['$scope', 'ItemsFactory', 'ItemFactory', '$location', '$route',
        function ($scope, ItemsFactory, ItemFactory, $location, $route) {

             $scope.modalShown = false;

         //callback for ng-click 'deleteItem':

            $scope.openModal = function (itemId) {
                $scope.modalShown = !$scope.modalShown;

            };

        //callback for ng-click 'deleteItem':

            $scope.deleteItem = function (itemId) {

                ItemFactory.delete({ id: itemId }).$promise.then(function (items){
                    $scope.items = items;
                    $location.path('/items'); 
                    $route.reload();
                }, function (err) {
                    console.error(err);
                });    

                // } 

            };

【问题讨论】:

标签: angularjs


【解决方案1】:

我在这方面花了一些时间,但我想一键完成所有操作(就像常规的窗口确认对话框一样)。它以问题“How do I intercept ng-click in angularJS?”开始

我开发了一个与 UI Bootstrap Modal 一起使用的指令和服务,以创建一个模态对话框,在继续之前确认 ng-click 操作。

Demo on Plunker 或这里:

/*
 Confirm an ng-click action with a modal dialog window (requires UI Bootstrap Modal service)
 Using this modal requires two things: apply the attribute to the dom element and prepend
 the confirmClick() action to the ng-click attribute.

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

 */
.directive('confirmClick', ['$q', 'dialogModal', function($q, dialogModal) {
    return {
        link: function (scope, element, attrs) {
            // ngClick won't wait for our modal confirmation window to resolve,
            // so we will grab the other values in the ngClick attribute, which
            // will continue after the modal resolves.
            // modify the confirmClick() action so we don't perform it again
            // looks for either confirmClick() or confirmClick('are you sure?')
            var ngClick = attrs.ngClick.replace('confirmClick()', 'true')
                .replace('confirmClick(', 'confirmClick(true,');

            // setup a confirmation action on the scope
            scope.confirmClick = function(msg) {
                // if the msg was set to true, then return it (this is a workaround to make our dialog work)
                if (msg===true) {
                    return true;
                }
                // 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?';
                // open a dialog modal, and then continue ngClick actions if it's confirmed
                dialogModal(msg).result.then(function() {
                    scope.$eval(ngClick);
                });
                // return false to stop the current ng-click flow and wait for our modal answer
                return false;
            };
        }
    }
}])

/*
 Open a modal confirmation dialog window with the UI Bootstrap Modal service.
 This is a basic modal that can display a message with okay or cancel buttons.
 It returns a promise that is resolved or rejected based on okay/cancel clicks.
 The following settings can be passed:

    message         the message to pass to the modal body
    title           (optional) title for modal window
    okButton        text for OK button. set false to not include button
    cancelButton    text for Cancel button. ste false to not include button

 */
.service('dialogModal', ['$modal', function($modal) {
    return function (message, title, okButton, cancelButton) {
        // setup default values for buttons
        // if a button value is set to false, then that button won't be included
        okButton = okButton===false ? false : (okButton || 'Confirm');
        cancelButton = cancelButton===false ? false : (cancelButton || 'Cancel');

        // setup the Controller to watch the click
        var ModalInstanceCtrl = function ($scope, $modalInstance, settings) {
            // add settings to scope
            angular.extend($scope, settings);
            // ok button clicked
            $scope.ok = function () {
                $modalInstance.close(true);
            };
            // cancel button clicked
            $scope.cancel = function () {
                $modalInstance.dismiss('cancel');
            };
        };

        // open modal and return the instance (which will resolve the promise on ok/cancel clicks)
        var modalInstance = $modal.open({
            template: '<div class="dialog-modal"> \
                <div class="modal-header" ng-show="modalTitle"> \
                    <h3 class="modal-title">{{modalTitle}}</h3> \
                </div> \
                <div class="modal-body">{{modalBody}}</div> \
                <div class="modal-footer"> \
                    <button class="btn btn-primary" ng-click="ok()" ng-show="okButton">{{okButton}}</button> \
                    <button class="btn btn-warning" ng-click="cancel()" ng-show="cancelButton">{{cancelButton}}</button> \
                </div> \
            </div>',
            controller: ModalInstanceCtrl,
            resolve: {
                settings: function() {
                    return {
                        modalTitle: title,
                        modalBody: message,
                        okButton: okButton,
                        cancelButton: cancelButton
                    };
                }
            }
        });
        // return the modal instance
        return modalInstance;
    }
}])

【讨论】:

  • 太棒了!
  • @dustin 你能告诉我如何用 id 而不是它的索引来删除它。如果每个项目都有一个ID。我正在使用 http.delete 删除而不是拼接
  • @codelearner,我的具体例子只是关于如何拦截点击动作以提示确认。在这个例子中,你可以自定义“deleteItem(item)”方法来做任何你想做的事情。如果确认了 confirmClick() 方法,它将触发第二个动作。
  • 对于新版本,你必须重命名$modal -> $uibModal$modalInstance -> $uibModalInstance
【解决方案2】:

item 仅在 ngRepeat 为每个元素创建的范围内“已知”。
&lt;modal-dialog&gt; 不在该范围内,也不了解 item

你可以这样重构代码:

// In HTML:
<modal-dialog ...>
    ...
    <button ng-click="deleteItem()" ...

// In controller:
$scope.modalShown = false;
$scope.itemToDeleteId;
...
$scope.openModal = function (itemId) {
    $scope.itemToDeleteId = itemId;
    $scope.modalShown = true;
};
...
$scope.deleteItem = function () {
    if (!$scope.itemToDeleteId) { return; }
    var itemId = $scope.itemToDeleteId;
    $scope.itemToDeleteId = null;
    ...

【讨论】:

    【解决方案3】:

    自定义指令:

    /**
     * A generic confirmation for risky actions.
     * Usage: Add attributes: ng-really-message="Really?" ng-really-click="takeAction()" function
     */
    angular.module('app').directive('ngReallyClick', [function() {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                element.bind('click', function() {
                    var message = attrs.ngReallyMessage;
                    if (message && confirm(message)) {
                        scope.$apply(attrs.ngReallyClick);
                    }
                });
            }
        }
    }]);
    

    【讨论】:

    • 那么这样你会如何改变确认框的样式呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 2013-05-18
    • 1970-01-01
    • 2016-02-28
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多