Use angular to mark modified elements in a list
Asked Answered
A

5

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/

Athome answered 8/7, 2015 at 17:30 Comment(7)
Would Angular's $pristine and $dirty work for you? docs.angularjs.org/api/ng/type/form.FormControllerEntremets
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.Hentrich
Will you please share more code ?Winny
This might help you #8573326Aorangi
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.Pippas
@Aorangi 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 againAthome
@Entremets Is it possible to instantiate this with an arbitrary object? The problem is that I do need to have the modified attributeAthome
C
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.

Contumacy answered 8/7, 2015 at 18:4 Comment(2)
The problem is that I want to bind to the attributesAthome
I get it.... I just hoped assigning other way round won't be a problem. Nice question btw. will wait for a perfect answer from someone's side.Contumacy
F
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);
Fromenty answered 8/7, 2015 at 19:20 Comment(0)
A
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).

Athome answered 16/9, 2015 at 9:13 Comment(0)
P
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/

Prisca answered 27/11, 2015 at 8:3 Comment(0)
B
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';
        };
Borroff answered 27/6, 2016 at 8:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.