Подтвердить что ты не робот

Angular Ресурс - как проверить, имеет ли экземпляр ресурса какие-либо несохраненные изменения?

Я хочу узнать, был ли пользовательский экземпляр $resource изменен, то есть, отличается ли его текущее состояние от того, что изначально было загружено с сервера && & еще не спасен. Как я могу это достичь?

4b9b3361

Ответ 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)
}