Я хочу узнать, был ли пользовательский экземпляр $resource изменен, то есть, отличается ли его текущее состояние от того, что изначально было загружено с сервера && & еще не спасен. Как я могу это достичь?
Angular Ресурс - как проверить, имеет ли экземпляр ресурса какие-либо несохраненные изменения?
Ответ 1
Предполагая, что вы получаете ресурс, а затем помещаете его в текущую область $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
может сообщить вам, произошло ли изменение. И когда вы сохраняете объект, reset $scope.userChange
.
Вы даже можете сделать это
$scope.$watch('question', function() {
$scope.question.$save();
}, true);
Очевидно, вы хотите добавить какую-то систему дроссельной заслонки или "debounce", чтобы она ждала секунду или около того, как только вы это сделаете, любое изменение объекта приведет к сохранению через $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
, см. этот вопрос для ответов на вопрос о том, как вы можете это сделать на сервисе и уровне factory, чтобы что-то сделать как это.
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
срабатывает, как только вы ее вызываете, а затем следит за изменениями. Нам не нужно сохранять первый вызов.
Ответ 2
Я нашел решение, которое не рассматривает загрузку данных с сервера как изменение пользователя и реализуется непосредственно в самой службе. Это может быть не самое эффективное решение, но обеспечивает именно ту функциональность, которую я хочу,
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;
}]);
Ответ 3
Вы можете клонировать исходный объект, а затем сравнивать, когда вам нужно проверить.
master = null
resource = Resource.get({id:1}, function() {
master = angular.copy(resource)
})
function isModified() {
return !angular.equals(resource, master)
}