7

I want to synchronize data, therefore I have a data object containing the current state. When this is changed I would like to set an attribute on the object so that I can filter by this when syncing. The object structure is:

data = {  
type1: [  
  {a:"a", b:"b"},...  
]  
type2: [  
  {c:"c", d:"d"},...  
]  
}  

For example if data.type1[0].a = "test" would be done, I would like to add modified: true to the object so that it would be

{a:"test", b:"b", modified:true}

I have tried $watch(data, function(), true) but I can not find how I can see which object was changed and searching both given data objects would be a large overhead. $watchcollection (when just looking for adding/deleting) also does not give an index.
Is there any way to find out which object was changed? Or is there an other library which can do this well?

Thank you

EDIT:
I created a jsfiddle: https://jsfiddle.net/yfo8xwah/

Peter Burkert
  • 461
  • 4
  • 13
  • 1
    Would Angular's `$pristine` and `$dirty` work for you? https://docs.angularjs.org/api/ng/type/form.FormController – Aaron Jul 08 '15 at 17:35
  • one way is there but not so efficient is `$watch` gives you `newVal` and `oldVal` and you can compare both to find which one was changed. – vinayakj Jul 08 '15 at 17:36
  • Will you please share more code ? – Vineet Jul 08 '15 at 17:36
  • This might help you http://stackoverflow.com/questions/8572826/generic-deep-diff-between-two-objects – yvesmancera Jul 08 '15 at 17:45
  • Angular doesn't store changed keys, it just collectes number of differences. So you either compare object manually yourself or ... do something else like implementing custom setter for data modification. – dfsq Jul 08 '15 at 17:53
  • @yvesmancera this actually compares the objects, but angular already recognized the change when using $watch so I was hoping that I do not have to iterate over the objects again – Peter Burkert Jul 08 '15 at 17:57
  • @Aaron Is it possible to instantiate this with an arbitrary object? The problem is that I do need to have the modified attribute – Peter Burkert Jul 08 '15 at 17:57

5 Answers5

0

Although this is a silly workaround but what you can do is to keep a method in data object like :

data = {type1 : {}, type2 : {}, ... , checkModification : function (field)
{data[field].modified = true; return data[field];}}

Now You can assign any object like this data.checkModification('type1').a = "test" This may give you satisfactory result.

binariedMe
  • 4,309
  • 1
  • 18
  • 34
0

Ok, I had made it work: https://jsfiddle.net/yfo8xwah/4/ .

First of all I have applied a simple watcher on the data model. Inside the watcher I have used this beautiful library for object comparing and matching any differences and inject the modification flag.

So my $watch function looks like this:

$scope.$watch(function () {
        return $scope.data;
    }, function (newD, oldD, scope) {
        //dont run on init mate ;)
        if (angular.equals(newD, oldD)) {
            return;
        }
        //now find the differences and apply em
        var diffs = objectDiff.diffOwnProperties(newD, oldD);
        console.log(diffs, "diffs");

        if (diffs.changed != "equal") {
            //you should solve this recursively ;)
            angular.forEach(diffs.value, function (value, key) {
                if (value.changed != "equal") {
                    angular.forEach(value.value, function (subvalue, subkey) {
                        if (subvalue.changed != "equal") {
                            $scope.data[key][subkey]["modified"] = true;
                        }
                    });
                }
            });
        }

    }, true);
vorillaz
  • 6,098
  • 2
  • 30
  • 46
0

After considering the different options, I decided that it was necessary to use custom getters/setters.

This is necessary as no real event handler exists and it would be very inefficient to always compare the whole data set (which might have a few thousand elements).

Peter Burkert
  • 461
  • 4
  • 13
0

I think this will help ......

var app = angular.module('sample', []);
app.controller("MyAppCtrl", function ($scope, $timeout) {
    $scope.data = {
        type1: [{
            a: "a",
            b: "b"
        }, {
            a: "c",
            b: "d"
        }],
        type2: [{
            m: 0,
            k: 1
        }, {
            m: 45,
            k: 92
        }]
    }

    $scope.$watch('data.type1[0].a', function () {
        console.log('data changed');
        $scope.data.type1[0].modified = true;
        console.log($scope.data.type1[0])
    });

});
<body ng-app="sample">
    <div ng-controller="MyAppCtrl">
        <input type="text" ng-model="data.type1[0].a">
        <br>
        <label>{{data.type1[0].a}}</label>
    </div>
</body>

https://jsfiddle.net/basilin/p92Lkn93/

Basilin Joe
  • 672
  • 1
  • 10
  • 23
0

Try it. Whenever particular object's property change by input like textbox

Than on change event pass that object to this function like below:

<input  data-ng-model="data.type1.a" type="text" 
        data-ng-change="onChage(data.type1)"/>
        $scope.onChage = function (object) {
            object.IsDirty = 'modified';
        };
チーズパン
  • 2,752
  • 8
  • 42
  • 63
alfishan aqeel
  • 220
  • 2
  • 5