AngularJS - 重置绑定对象的状态

AngularJS - Reset the state of a bound object

我对一些书进行了非常简单的重复,当用户单击该书时,它会打开一个新模式。他们可以在哪里编辑这本书。当我使用双向绑定时,'display page' 会在我在模态上键入时自动更改 - 这非常棒。

然而我想要做的是允许用户按下取消按钮,并且书的状态回到它被改变之前的状态。这是否可能在 Angular 中而不返回并重置整个 $scope.books 对象?

在实际应用程序中,这将是一个 API 调用,除非完全必要,否则我宁愿不进行另一个服务器调用。是否已经有一种模式可以解决这个问题?

(function(){
    var app = angular.module('ngModalDemo', ['ui.bootstrap']) 
    .controller('formController', function($scope, $modal, $log){

        $scope.books = [
            { Id: 1, Name:'A Feast For Crows'},
            { Id: 2, Name:'Before they are Hanged'}
        ];

        $scope.openModal = function (currentBook) {             
            var modalInstance = $modal.open({
                templateUrl: 'SomeModal.html',
                controller: [
                    '$scope', '$modalInstance', function($scope, $modalInstance){
                        $scope.editBook = currentBook;
                        $scope.saveModal = function (book) {
                            $modalInstance.close();
                        };
                        $scope.cancelModal = function () {
                            //  Restore the previous state here!
                            $modalInstance.close();
                        };
                    }]
            });
        };
    })
})();

<div ng-controller="formController">

    <p ng-repeat="displayBook in books">
         <a href="#" ng-click="openModal(displayBook)">{{displayBook.Name}}</a>
    </p>    

    <script type="text/ng-template" id="SomeModal.html">
        <form name="editForm" ng-submit="saveModal(editBook)" noValidate>
            <div class="modal-header">
                Name: <input ng-model="editBook.Name" required /><br />
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-warning" ng-click="cancelModal()">Cancel</button>
                <button class="btn btn-info" ng-disabled="editForm.$dirty && editForm.$invalid">Save</button>
            </div>
        </form> 
    </script>
</div>

您可以创建对象的深层副本到临时文件,然后在必要时将其设置回去:

var temp = angular.copy(currentBook);
$scope.editBook = currentBook;
$scope.saveModal = function (book) {
    $modalInstance.close();
};
$scope.cancelModal = function () {
    //  Restore the previous state here!
    angular.copy(temp, $scope.editBook);
    $modalInstance.close();
};

Angular 有方法 copy 可以通过克隆对象或数组为您完成工作。

想法是将数据的 copy 传递给模态而不是实例本身。所以当用户按下 Cancel 时,主实例不会改变。

在你的情况下:

$scope.editBook = currentBook;

写:

$scope.editBook = angular.copy(currentBook);

考虑在显示模式之前缓存原始模型的副本,然后在用户取消时重置它。这可以直接在 JavaScript 中轻松完成,或者您可以选择使用 Angular 的 $cacheFactory 来处理更复杂的场景。

例如,您可以将索引添加到 ng-repeat:

<p ng-repeat="displayBook in books track by $index">
     <a href="#" ng-click="openModal(displayBook, $index)">
          {{displayBook.Name}}
     </a>
</p>

然后更改您的控制器方法以在用户取消模态时重置 $scope.books 集合:

$scope.openModal = function (currentBook, idx) {             
    // Cache the book, so that we can reset it later.
    var cachedBook = angular.copy(currentBook);
    var $outerScope = $scope;

    var modalInstance = $modal.open({
        // ...
        controller: [
            '$scope', '$modalInstance', function($scope, $modalInstance){
                $scope.editBook = currentBook;
                $scope.saveModal = function (book) {
                    // ...
                };
                $scope.cancelModal = function () {
                    //  Restore the previous state
                    $outerScope.books[idx] = cachedBook;

                    // ...
                };
            }]
    });
};

如果您预计您的用户点击 Cancel 的次数比他们实际保存编辑的次数多,那么也许可以考虑反转操作并传入书籍的副本而不是原件,只修改原件在调用 saveModal 之后。