Question

I am trying to implement an editor for a model with a lot of fields that has an autosave feature.

The model is json, it is loaded with $resource and used directly in the scope.

 MyModelResource = $resource(config.api4resource + 'models/:id', {id:'@_id'});
 $scope.myModel = MyModelResource.get({id: xxxx});

Problem #1: The actual autosave implementation. For each text field I am doing:

HTML:

<input type="text" ng-model="myModel.someField" ng-blur="save()" ng-change="dirty()">

Controller:

$scope.dirty = function() {
    $scope.dirtyFlag = true;
    console.log('Marking dirty!');
};

$scope.save = function(force) {

    if (!$scope.dirtyFlag && !force) {
        return;
    }
    $scope.dirtyFlag = false;
    console.log('Saving!');
    $scope.myModel.$save();
}

The idea is, that saving on each ng-change is too expensive, as I don't want to hit the server for every letter as user types. So ng-change() marks a "dirty" flag in my controller, and when I move away from the field with ng-blur, I check the flag and save only if the state is dirty. This still doesn't cover all the cases, like the case when user modified the text field but did not move to another field. There is an option to schedule a timer for save() from within dirty(), so that I will save anyway, but this doesn't look like an elegant solution to me (the timer code taken from https://stackoverflow.com/a/21137079/1076865):

$scope.dirty = function() {
    $scope.dirtyFlag = true;
    console.log('Marking dirty!');

    if (savePromise) {
        $timeout.cancel(savePromise);
    }

    savePromise = $timeout(function() {
        savePromise = null;
        $scope.save();
    }, 500);
};

What are the common ways of solving that problem?

Problem #2: Once my save code is actually hit, I am calling myModel.$save() function. This eventually sends a POST request to the server, the server saves it in DB and replies back with the same model as a response.

And here is the problem, it seems to cause a reload of myModel, which causes a reflow of some portions of the webpage and focus is being lost. So if a user typed something and pressed TAB to move to the next field, a moment later (once the reply comes back) the focus disappears from that new field. Pretty annoying. How can I solve that problem? Do I need to keep two copies of the model myself (one that is used with $resource and another one on the $scope), and keep track manually of changes between the two? That doesn't sound like an angular way, there must be a better solution.

Thanks!

Was it helpful?

Solution

Problem #1

I would use something like Lo-Dash debounce. A quick google search shows How to auto save with angular and debounce which also prevents you from having to add ng-blur and ng-change to each input. And should be more efficent for users who edit multiple inputs quickly.

Problem #2

Sounds like $scope.$apply() or $scope.$digest() is being called after resource.$save() but not sure why.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top