【问题标题】:Angular Resource - how to check if a resource instance has any unsaved changes?Angular Resource - 如何检查资源实例是否有任何未保存的更改?
【发布时间】:2013-11-06 01:49:41
【问题描述】:

我希望能够判断 $resource 实例是否已被用户修改 - 即,它的当前状态是否与最初从服务器加载的状态不同 && 尚未 $saved。我怎样才能做到这一点?

【问题讨论】:

    标签: javascript angularjs angularjs-service angularjs-resource


    【解决方案1】:

    您可以克隆初始对象,然后在需要检查时进行比较。

    master = null
    resource = Resource.get({id:1}, function() {
      master = angular.copy(resource)
    })
    function isModified() {
      return !angular.equals(resource, master)
    }
    

    【讨论】:

    • 虽然这样解决了问题,但是对于一个对象比较来说是非常昂贵的。如果你在视图中使用这样的函数,这种昂贵的比较算法将在每个摘要周期运行,从而使应用程序变慢。
    【解决方案2】:

    假设你得到一个资源,然后把它放在当前的 $scope 上以便用户可以编辑它:

    $scope.question = Questions.get({id:"19615328"});
    

    然后您可以观察它是否有这样的变化:

    // some flag, name it anything
    $scope.userChange = false;
    $scope.$watch('question', function(newValue, oldValue) {
        if(newValue && newValue != oldValue){
            $scope.userChange = true;
            // if you want to you can even do this, this will trigger on every change though
            $scope.question.$save();
        }
    }, true);
    

    下面的几乎所有内容都是下面聊天中额外问题的结果

    然后每当您想检查它是否已更改时,$scope.userChange 可以告诉您是否发生了更改。当你保存对象时,重置$scope.userChange

    你甚至可以这样做

    $scope.$watch('question', function() {
        $scope.question.$save();
    }, true);
    

    显然,您希望添加某种节流或“去抖动”系统,以便它等待一秒钟左右,一旦您完成此操作,对对象的任何更改都会通过$scope.$watch 进行保存。

    如果你想检查 null,当你还没有收到实际对象时。

    $scope.$watch('question', function(newValue, oldValue) {
        // dont save if question was removed, or just loaded
        if(newValue != null && oldValue != null){
            $scope.question.$save();
        }
    }, true);
    

    您甚至可以封装Questions.get 调用,参见this questions for answers on how you can do this on the service & factory level,以执行类似的操作。

    Questions.getAndAutosave = function(options){
        var instance = Questions.get(options);
        $scope.$watch(function(){
                return instance;
            },
            function(newValue, oldValue){
                if (newValue === oldValue) return;
                if(newValue != null && oldValue != null){
                    instance.$save();
                }
            }, true);
        return instance;
    };
    

    然后,无论何时您调用Questions.getAndAutosave,它返回的任何内容都已被监视,并且将自动为$save'd。我们这样做的原因if (newValue === oldValue) return; 是因为$watch 在您调用它时立即触发,然后监视更改。我们不需要在第一次调用时保存。

    【讨论】:

    • 不幸的是,执行 $get 时也会触发 $watch,因为 $scope.question 从 null 更改为 object... 我想要一些仅在用户进行更改时报告未保存更改的东西,不是在从服务器中提取数据时。
    • 这个想法是您在收到回复后观看它。要么;给 $watch 第二个回调,(这会接收旧值和新值),因此您可以检查旧值是否为空。 (或者如果新值为空?:-))
    • 另外,你认为这样的功能可以直接在服务中实现吗?我知道我可以使用附加功能来增加 $resource。在每个控制器中为每个资源实现这些功能可能很乏味,而且远非优雅
    • 我已经添加了一个关于你可以做什么的简短示例,还有一个关于如何在服务/工厂级别配置它的许多选项的问题。
    • 由于某种原因,$watch 中的if(newValue != null && oldValue != null){ 条件是不够的。我已经实现了它,并且在加载资源后立即将 $scope.userChange 标志设置为 true,即使用户尚未对对象进行任何更改。关于如何纠正的任何想法?
    【解决方案3】:

    我找到了一个解决方案,它不会将从服务器下载数据视为用户更改,而是直接在服务本身中实现。它可能不是最有效的解决方案,但提供了我想要的功能,

    app.factory('testService', ['$resource', '$rootScope', function($resource, $rootScope){
    var test = $resource('/api/words/:id', {id: '@id'});
    
    test.orig_get = test.get;
    
    test.get = function(options){
        var instance = test.orig_get(options, function(){
            instance.unsaved = false;
            $rootScope.$watch(function(){
                return instance;
            }, function(newValue, oldValue) {
               if(angular.equals(newValue, oldValue)){
                    return;
               }
               var changed_indexes = [];
               for(var i in newValue){
                    if(!angular.equals(newValue[i], oldValue[i])){
                        changed_indexes.push(i);
                    }
               }
               if(newValue != null && oldValue != null && !(changed_indexes.length==1 && changed_indexes[0]=='unsaved')){
                    console.log('detected change. setting unsaved to true');
                    instance.unsaved = true;
                }
    
            }, true);
        });
        return instance;
    }
    
    test.prototype.orig_save = test.prototype.$save;
    
    test.prototype.$save = function(options){
        return this.orig_save(options, function(){
            this.unsaved = false;           
        })
    }
    
    return test;
    }]);
    

    【讨论】:

      猜你喜欢
      • 2011-03-09
      • 1970-01-01
      • 2017-12-11
      • 1970-01-01
      • 2018-03-09
      • 1970-01-01
      • 2014-03-05
      • 1970-01-01
      • 2010-11-24
      相关资源
      最近更新 更多