【发布时间】:2013-11-06 01:49:41
【问题描述】:
我希望能够判断 $resource 实例是否已被用户修改 - 即,它的当前状态是否与最初从服务器加载的状态不同 && 尚未 $saved。我怎样才能做到这一点?
【问题讨论】:
标签: javascript angularjs angularjs-service angularjs-resource
我希望能够判断 $resource 实例是否已被用户修改 - 即,它的当前状态是否与最初从服务器加载的状态不同 && 尚未 $saved。我怎样才能做到这一点?
【问题讨论】:
标签: javascript angularjs angularjs-service angularjs-resource
您可以克隆初始对象,然后在需要检查时进行比较。
master = null
resource = Resource.get({id:1}, function() {
master = angular.copy(resource)
})
function isModified() {
return !angular.equals(resource, master)
}
【讨论】:
假设你得到一个资源,然后把它放在当前的 $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 在您调用它时立即触发,然后监视更改。我们不需要在第一次调用时保存。
【讨论】:
if(newValue != null && oldValue != null){ 条件是不够的。我已经实现了它,并且在加载资源后立即将 $scope.userChange 标志设置为 true,即使用户尚未对对象进行任何更改。关于如何纠正的任何想法?
我找到了一个解决方案,它不会将从服务器下载数据视为用户更改,而是直接在服务本身中实现。它可能不是最有效的解决方案,但提供了我想要的功能,
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;
}]);
【讨论】: