在angularJS中自定义删除确认

时间:2014-04-07 14:15:07

标签: angularjs

我有一个带有项目列表的角度应用程序。我正在尝试实施自定义"确认删除"模态,以便当用户点击"删除"项目旁边的按钮,模式打开以确认删除。单击"是",将触发deleteItem()函数。我的问题是服务器返回404找不到删除请求。它在我使用标准的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);
                });    

                // } 

            };

3 个答案:

答案 0 :(得分:18)

我花了一些时间在这上面,但我想一键完成(如常规窗口确认对话框)。它始于问题&#34; How do I intercept ng-click in angularJS?&#34;

我开发了一个与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;
    }
}])

答案 1 :(得分:2)

item仅在ngRepeat为每个元素创建的范围内“已知”。
<modal-dialog>不在该范围内且不了解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;
    ...

答案 2 :(得分:0)

自定义指令:

/**
 * 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);
                }
            });
        }
    }
}]);