Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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())?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

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; }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading