Javascript 角度资源-如何检查资源实例是否有任何未保存的更改?
我想知道用户是否修改了$resource实例,也就是说,它的当前状态是否与最初从服务器加载的状态不同&尚未保存$resource实例。如何实现这一点?假设您获得一个资源,然后将其放在当前的$scope上,以便用户可以编辑它:Javascript 角度资源-如何检查资源实例是否有任何未保存的更改?,javascript,angularjs,angularjs-service,angularjs-resource,Javascript,Angularjs,Angularjs Service,Angularjs Resource,我想知道用户是否修改了$resource实例,也就是说,它的当前状态是否与最初从服务器加载的状态不同&尚未保存$resource实例。如何实现这一点?假设您获得一个资源,然后将其放在当前的$scope上,以便用户可以编辑它: $scope.question = Questions.get({id:"19615328"}); 然后,您可以观察它是否有如下变化: // some flag, name it anything $scope.userChange = false; $scope.$wa
$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.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
,它返回的任何内容都已被监视,并将自动保存。如果(newValue==oldValue)返回,则执行的原因
是因为$watch
会在您调用它时立即激发,然后监视更改。我们不需要在第一次呼叫时保存数据。我发现了一种解决方案,它既不将从服务器下载数据视为用户更改,也直接在服务本身中实现。它可能不是最有效的解决方案,但提供了我想要的功能
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;
}]);
您可以克隆初始对象,然后在需要检查时进行比较
master = null
resource = Resource.get({id:1}, function() {
master = angular.copy(resource)
})
function isModified() {
return !angular.equals(resource, master)
}
不幸的是,在执行$get时,$watch也会被触发,因为$scope.question会从null变为object。。。我想要的东西只有在用户做出更改时才会报告未保存的更改,而不是在从服务器提取数据时。其想法是在收到响应后再进行查看。或给$watch第二次回调(接收新旧值),以便检查旧值是否为null。(或者如果新值为null?:-)同样,您认为这样的功能可以直接在服务中实现吗?我知道我可以用附加功能来扩充$resource。在每个控制器中为每个资源实现这些功能可能会很乏味,而且远不是很优雅。我已经添加了一个关于您可以做什么的简短示例,还有一个关于如何在服务/工厂级别配置它的问题,有很多选项。出于某种原因,if(newValue!=null&&oldValue!=null){
在$watch中的条件是不够的。我已经实现了它,并且在资源加载后立即将$scope.userChange标志设置为true,即使用户还没有对对象进行任何更改。关于如何更正这一点,您有什么想法吗?虽然这解决了问题,但对对象进行比较非常昂贵。如果在视图中使用这样的函数,这种昂贵的比较算法将在每个摘要周期中运行,使应用程序运行缓慢。