Home > other >  Javascript: update nested object values from array of update objects
Javascript: update nested object values from array of update objects

Time:10-09

I have a nested object with no pre-determinable path to child objects - example:

{
    children : 
    [
        {
            children : 
            [
                {
                    children : 
                    [
                        {
                            id : "F100517B-D00F",
                            level : 4,
                            note : "update me",
                            parentId : "23A2A0DB-CCE3",
                            title : "change me"
                        }
                    ],
                    id : "23A2A0DB-CCE3",
                    level : 3,
                    note : "me too",
                    parentId : "a0H4H00000Roi",
                    title : "..and me"
                }
            ],
            id : "a0H4H00000Roi",
            level : 2,
            note : "none",
            parentId : "0064H00000ysL",
            title : "pending"
        },
        {
            "children" : 
            [
                {
                    id : "6A45E2EC-7825",
                    level : 3,
                    note : "|",
                    parentId : "a0H4H00000Roi",
                    title : ""
                }
            ],
            id : "a0H4H00000Roi",
            level : 2,
            note : "",
            parentId : "0064H00000ysL",
            title : "Change me"
        }
    ],
    id : "0064H00000ysL",
    level : 1,
    note : "hello",
    title : "Test Co"
}

Following this I generate a list of updates via a map function - sample results:


    [{
      content: "New Co",
      id: "0064H00000ysL",
      note: "Here's your update"
    }, {
      content: "91%",
      id: "a0H4H00000Roi",
      note: "New note here"
    }]

I need to iterate through the update object array and update nested object values, I've tried a few things but can't seem to quite nail it (my JS skill is a bit limited atm).

Here's my last attempt, taken from the closest solution I found here: Javascript update values in nested object by array path

    var updates = $('div.node').map(function() {
    return {
              id: $(this).attr("id"),
              content: $(this).find('div.content').text(),
              note: $(this).find('div.note').text()
           };
       }).get();

const checkAndChange = (obj, update) => { //function to check id match for update
  if (update.id.includes(obj.id)) {
    obj.title = update.content;
    obj.note = update.note;
  }
}

const recursion = (obj, update) => {
   const o = obj;
   checkAndChange(o, update); // check if id exists update values
   if (o.children.length > 0) { //check if has children
        o.children.forEach(v => { //if has children do same recursion for children
        recursion(v, update);
      });
   }
   return o; //return updated object
}
var updatesLength = updates.length;
for(let it = 0; it < updatesLength; it  ) {
    recursion(obj, updates[it]);
}

console.log(obj)

The indented map function at the top works fine but I get Uncaught TypeError: Cannot read properties of undefined (reading 'id')" when I try to loop though the update array and write back to the main object (obj).

Any help appreciated

CodePudding user response:

You can use a redursive approach here, we'll create a function updateNestedObj() to apply the updates, applying to each object and any of its child objects:

const objToUpdate = { children : [ { children : [ { children : [ { id : "F100517B-D00F", level : 4, note : "update me", parentId : "23A2A0DB-CCE3", title : "change me" } ], id : "23A2A0DB-CCE3", level : 3, note : "me too", parentId : "a0H4H00000Roi", title : "..and me" } ], id : "a0H4H00000Roi", level : 2, note : "none", parentId : "0064H00000ysL", title : "pending" }, { "children" : [ { id : "6A45E2EC-7825", level : 3, note : "|", parentId : "a0H4H00000Roi", title : "" } ], id : "a0H4H00000Roi", level : 2, note : "", parentId : "0064H00000ysL", title : "Change me" } ], id : "0064H00000ysL", level : 1, note : "hello", title : "Test Co" } 

const updateArr = [{ content: "New Co", id: "0064H00000ysL", note: "Here's your update" }, { content: "91%", id: "a0H4H00000Roi", note: "New note here" }];

function updateNestedObj(obj, updates) {
    const updateToApply = updates.find(upd => upd.id === obj.id);
    if (updateToApply) {
        obj.title = updateToApply.content;
        obj.note = updateToApply.note;
    }
    // Apply updates to any child objects
    for(let k in obj) {
        if (typeof(obj[k]) === 'object') {
            updateNestedObj(obj[k], updates);
        }
    }
}

updateNestedObj(objToUpdate, updateArr);

console.log(objToUpdate)
        
.as-console-wrapper { max-height: 100% !important; top: 0; }

  • Related