2

I have two object that I want to merge in a new object, the first object is for default options for a google chart:

optionsA = {
    height: 500,
    focusTarget: 'category',
    hAxis: {
      showTextEvery: 0,
      slantedText: true,
      slantedTextAngle: 45,
      format: 'date',
    },
}

With my second object I want to add some properties to hAxis and override present options with the new values but I want to keep the options by default in optionsA.

This is my second object:

optionsA = {
    isStacked: true,
    hAxis: {
      gridlines: {
        count: 10
      },
      format: 'percent',
    },
}

These objects are more complex but I reduce the properties to simplify the question

When I try to merge with object.assign the result is that object B add new root properties to the new object, but properties in hAxis is complete overrided with the options in optionsB.

let newObj = Object.assign({}, optionsA, optionsB);

This is the object that I want expected:

{
    height: 500,
    focusTarget: 'category',    
    isStacked: true,
    hAxis: {
      gridlines: {
         count: 10
      },
      format: 'percent',
      showTextEvery: 0,
      slantedText: true,
      slantedTextAngle: 45,
    },
}

but instead of this I am getting this:

{
    height: 500,
    focusTarget: 'category',    
    isStacked: true,
    hAxis: {
       gridlines: {
         count: 10
       },
       format: 'percent',
    },
}

Properties in hAxis are completely override with the new properties, what's wrong with my aproach?

xzegga
  • 3,051
  • 3
  • 25
  • 45
  • 2
    `Object.assign()` only operates on the top-level properties of the source objects. It does not "descend" into sub-objects. – Pointy Apr 25 '17 at 15:20
  • Refer to this- http://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge – Sanchay Kumar Apr 25 '17 at 15:39
  • 1
    `Object.assign({}, optionsA, optionsB, {hAxis: Object.assign({}, optionsA.hAxis, optionsB.hAxis)})` should do it – Bergi Apr 25 '17 at 16:00

2 Answers2

3

If the nesting is not deep, you can break the merge process in two steps like below:

optionsA = {
    height: 500,
    focusTarget: 'category',
    hAxis: {
      showTextEvery: 0,
      slantedText: true,
      slantedTextAngle: 45,
      format: 'date',
    }
};

optionsB = {
    isStacked: true,
    hAxis: {
      gridlines: {
        count: 10
      },
      format: 'percent',
    }
};

let newNestedMerged = Object.assign({},optionsA.hAxis, optionsB.hAxis);
optionsA.hAxis = newNestedMerged;
optionsB.hAxis = newNestedMerged;
let newObj =  Object.assign(optionsA, optionsB);
console.log(newObj);

Does this help?

Pankaj Shukla
  • 2,657
  • 2
  • 11
  • 18
1

Because you have the same property in both object.

The properties are overwritten by other objects that have the same properties later in the parameters order.

Let see the example of assign in MDN.

My proposal is merge the same properties first.

optionsA = {
    height: 500,
    focusTarget: 'category',
    hAxis: {
      showTextEvery: 0,
      slantedText: true,
      slantedTextAngle: 45,
      format: 'date',
    },
}
optionsB = {
    isStacked: true,
    hAxis: {
      gridlines: {
        count: 10
      },
      format: 'percent',
    },
}
Object.assign(optionsA.hAxis, optionsB.hAxis);
let newObj = Object.assign({}, optionsB, optionsA);
console.log(newObj);
taile
  • 2,738
  • 17
  • 29
  • Good aproach but not work for me, This is a simple example of the object, actually there are a lot of properties that I need to merge. – xzegga Apr 25 '17 at 15:45
  • 1
    Yeah, I think here is the thing you are looking for. Hope that helps :) http://stackoverflow.com/a/383245/4886453 – taile Apr 25 '17 at 15:51
  • Thanks @tai-le you save my day! – xzegga Apr 25 '17 at 23:17
  • Cool :) Glad to know. If it's helpful for you. Lets accept it :) – taile Apr 26 '17 at 23:14
  • Sorry @tai-le but is the answer in your comment that actually help me., Object .assign merge only root properties and this doesn't work for me – xzegga Apr 27 '17 at 03:54