1

Explanation : Child component method has been called from parent component with an array of objects as a parameter. In child component, assigning this array into a variable.

Parent component :

let obj = [{
             'prop1': 'value1',
             'prop2': 'value2'
           },{
             'prop1': 'value1',
             'prop2': 'value2'
           }];

this.child.sendObject(obj);

Child component :

public sendObject(obj) : void {
   this.updatedObj = obj;
}

Problem statement :

  • Properties of the objects passed from parent component can be updated and send to child component.

    Parent component :

      let obj = [{
             'prop1': 'value4',
             'prop2': 'value2'
           },{
             'prop1': 'value1',
             'prop2': 'value7'
           }];
    
      this.child.sendObject(obj);
    
  • New objects can be added in the child component itself in the obj array.

    Child component :

      public sendObject(obj) : void {
         this.updatedObj = obj;
      }
    
      public addNewObj() {
         this.updatedObj.push({
           'prop3': 'value3',
           'prop4': 'value4 
         })
      }
    

I want to validate (check equality) the previously send object with this updated object.

What I tried so far ?

Child component :

public sendObject(obj) : void {
    const copy = JSON.parse(JSON.stringify(obj));
    this.updatedObj = obj;

    if (JSON.stringify(this.updatedObj) === JSON.stringify(copy)) {
       console.log("Not changed");
    } else {
       console.log("Changed");
    }
}

Above logic is working fine if the objects properties modified from the parent but if i added any new object into the existing array (this.updatedObj) in the child component and switches back from parent to child. It breaks and shows only objects passed from the parent.

Debug Diva
  • 26,058
  • 13
  • 70
  • 123
  • In your last block of code, you assign a copy of `obj` to `let copy`, then assign `obj` to `this.updatedObj` and finally compare if `copy` and `this.updatedObj` are the same, they will always be the same, because you just assigned the same `obj` to both variables – PitchBlackCat Feb 06 '19 at 14:55
  • Also, since you assign `obj` immediatly to `this.updatedObj`, whatever the child component set it to will be overwritten. I have to agree with @ludevik, though. You will save yourself a lot of headaches by making only 1 component responsible for the `obj`. – PitchBlackCat Feb 06 '19 at 14:56

2 Answers2

2

Only one component should be 'owner' of the array. In your case it looks like parent should be responsible for this. Child component should then not push the data to the array directly but instead should emit event to its output with the data it wants to add and parent should push those data into array.

Ludevik
  • 6,954
  • 1
  • 41
  • 59
1

Your solution using JSON.stringify is fragile because there are no guaranties for the key ordering inside objects. These objects are the same, but the comparison will fail:

let obj1 = { 'prop1': 'value1', 'prop2': 'value2' };

let obj2 = { 'prop2': 'value2', 'prop1': 'value1' };

You could recursively sort each objects keys before stringfying them, but it will be slow due to sorting and stringfying.

You can use a "deep equal" function from a library like Lodash (https://lodash.com/docs#isEqual) or Underscore (https://underscorejs.org/#isEqual).

If you want to build your own comparison function take a look at this question's answers: Object comparison in JavaScript

Leonardo Vidal
  • 553
  • 5
  • 7