Auto save with Angular
A service + directive that enables autosave on lost focus
HTML
<script src="http://code.angularjs.org/1.1.0/angular.min.js"></script>
<script src="http://underscorejs.org/underscore-min.js"></script>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<div ng-app="app" class="container">
<div ng-controller="Ctrl" class="row">
<div class="span5 well">
<input id="first" type="text" ng-model="texts.first" class="span2"/>
<p class="span2 pull-right">{{texts.first}}</p>
<input id="second" type="text" ng-model="texts.second" class="span2"/>
<p class="span2 pull-right">{{texts.second}}</p>
</div>
</div>
JavaScript
var $scope;
var app = angular.module('app', []);
function Ctrl($scope, pendingServerInteractions) {
$scope.texts = {
first: 'First',
second: 'Second'
};
$scope.$watch('texts', function(newValue, oldValue) {
if (newValue != oldValue) {
console.log('texts changed: ' + JSON.stringify($scope.texts));
pendingServerInteractions.add('texts', function() {
console.log('saving: ' + JSON.stringify(newValue));
//do your save thing
});
}
}, true);
}
app.directive('input', function(uiState) {
return {
restrict: 'E',
scope: false,
link: function(scope, element, attrs) {
$(element).bind('blur', function(e) {
scope.$apply(uiState.blur(element));
});
$(element).bind('focus', function(e) {
scope.$apply(uiState.focus(element));
});
}
};
});
app.factory('pendingServerInteractions', function(uiState, $rootScope) {
var registry = {};
pendingServerInteractions = {
/**
* Adds an interaction that should be performed later to the registry under the
* given key.
*
* If an interaction already existed under this key the old interaction will be
* overwritten and not executed.
*
* @param {string} key The key under which to store the interaction
* @param {function()} interaction The interaction function to be executed later
*/
add: function(key, interaction) {
registry[key] = interaction;
},
/**
* @private
*
* Will be called by a watch on focussed state. Executes all pending interactions.
*/
executeCallbacks: function() {
_.forEach(registry, function(value, key, myMap) {
if (value) {
value(key);
}
});
...