Skip to content
Advertisement

Javascript – Deeply change property value inside array of objects?

I have an array of objects. Each object looks like this:

{
    "key": "pQSa6jgmsbFnQgJ1memDJ",
    "type": "div",
    "props": {
        "id": "pQSa6jgmsbFnQgJ1memDJ",
        "style": {
            "height": "100px",
            "backgroundColor": "#de4141"
        },
        "className": ""
    },
    "selected": true,
    "childNodes": [{
        "key": "pQSa6jgmsbFnQgJ1memDJ",
        "type": "div",
        "props": {
            "id": "VrrQ1rMUOF6IOOKAZomor",
            "style": {
                "height": "100px",
                "backgroundColor": "#de4141"
            },
            "className": ""
        },
        "selected": false,
        "childNodes": []
    }]
}

The problem is that each object can have childNodes, and those childs can have also more childs… The property that I want to change is selected. This property defines wether the object is selected or not and therefore display a different className in the DOM. I have a function to deselect all (change all the object’s selected property to false) that looks like this, where content is a React state, the array containing this objects:

function () {
      const $ = _.cloneDeep(content);
      const z = $.map((c) => {
        let y = c;
        if (y?.childNodes && y.childNodes.length > 0) {
          y.childNodes = y.childNodes.map((h) => {
            let x = h;
            x.selected = false;
            return x;
          });
        }
        y.selected = false;
        return y;
      });
      setContent(z);

      setActive(null);
}

But this will only change the first childNodes. What if these childNodes have also more childNodes? I would need to do a map, again, for those childNodes manually. Is there a way to do this (e.g using lodash,which I’m alreay using for cloneDeep())?

Advertisement

Answer

You could use a recursive approach to set the required property values. We’d create a function like ‘setPropertyDeep’, pass along the property value required.

This will update the object tree to any depth.

const input = { "key": "pQSa6jgmsbFnQgJ1memDJ", "type": "div", "props": { "id": "pQSa6jgmsbFnQgJ1memDJ", "style": { "height": "100px", "backgroundColor": "#de4141" }, "className": "" }, "selected": true, "childNodes": [{ "key": "pQSa6jgmsbFnQgJ1memDJ", "type": "div", "props": { "id": "VrrQ1rMUOF6IOOKAZomor", "style": { "height": "100px", "backgroundColor": "#de4141" }, "className": "" }, "selected": false, "childNodes": [] }] }

function updatePropertyDeep(obj, property, value) {
    for(let k in obj) {
       if (k === property) {
           obj[property] = value;
       } else if (obj[k] && typeof(obj[k]) === 'object') { 
           updatePropertyDeep(obj[k], property, value);
       }
    }
    return obj;
}

console.log('Setting true:', updatePropertyDeep(input, 'selected', true))
console.log('Setting false:', updatePropertyDeep(input, 'selected', false))
.as-console-wrapper { max-height: 100% !important; }
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement