Desidero essere in grado di determinare se un'istanza $ resource è stata modificata dall'utente, ovvero se il suo stato corrente è diverso da quello caricato inizialmente dal server & & non è stato ancora salvato $. Come posso ottenerlo?Risorsa angolare: come verificare se un'istanza di risorsa presenta modifiche non salvate?
risposta
Supponendo che si ottiene una risorsa, e poi metterlo sul $ ambito corrente in modo che possa essere modificato da un utente:
$scope.question = Questions.get({id:"19615328"});
si può quindi guardare per i cambiamenti come questo:
// 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);
(Praticamente tutto da qui è il risultato delle domande in più dalla chat di sotto)
Poi ogni volta che vuoi per verificare se è stato modificato $scope.userChange
puoi dirti se si è verificata una modifica. E quando si salva l'oggetto, ripristinare $scope.userChange
.
Si può anche fare questo
$scope.$watch('question', function() {
$scope.question.$save();
}, true);
Ovviamente ci si vuole aggiungere una sorta di valvola a farfalla o di un sistema "di rimbalzo" in modo che aspetta un secondo o giù di lì, una volta che hai questo in atto alcuna modifica del oggetto causerà un salvataggio tramite $scope.$watch
.
E nel caso in cui si desidera verificare null, per quando non si è ancora ricevuto l'oggetto effettivo.
$scope.$watch('question', function(newValue, oldValue) {
// dont save if question was removed, or just loaded
if(newValue != null && oldValue != null){
$scope.question.$save();
}
}, true);
Si potrebbe anche avvolgere la chiamata Questions.get
, vedere this questions for answers on how you can do this on the service & factory level, a fare qualcosa di simile.
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;
};
Poi ogni volta che si chiama Questions.getAndAutosave
, qualunque esso ritorna già essere osservato, e sarà automatica $save
'd. Il motivo per cui facciamo if (newValue === oldValue) return;
è dovuto al fatto che lo $watch
si attiva non appena lo chiami e quindi cerca le modifiche. Non è necessario salvare la prima chiamata.
Ho trovato una soluzione che non tratta il download dei dati dal server come modifica dell'utente ed è implementata direttamente nel servizio stesso. Potrebbe non essere possibile la soluzione più efficiente, ma fornisce esattamente la funzionalità che voglio,
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;
}]);
è possibile clonare l'oggetto iniziale, quindi confrontare quando è necessario controllare.
master = null
resource = Resource.get({id:1}, function() {
master = angular.copy(resource)
})
function isModified() {
return !angular.equals(resource, master)
}
Anche se questo risolve il problema, è molto costoso un confronto tra oggetti. Se usi una funzione come questa nella vista, questo costoso algoritmo di confronto verrà eseguito su ogni ciclo di digestione, rendendo l'app rallentata. –
Purtroppo il $ orologio sarà anche essere attivato quando viene eseguita $ get, perché $ scope.question cambia da null per oggetto ... voglio qualcosa che avrebbe riferito solo le modifiche non salvate quando l'utente apporta le modifiche, non quando i dati vengono estratti dal server. –
L'idea è di guardarlo _dopo_ si riceve la risposta. O; dare $ guardare un secondo callback, (questo riceve il vecchio e il nuovo valore), in modo da poter verificare se il vecchio valore era nullo. (O se il nuovo valore è nullo? :-)) – Philipp
potresti fornire un esempio pronto? –