Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update value of nested array of objects

This is my actual array :

let mainArray= [
    {
        value: '/AG_TURF-123',
        label: 'Ag & Turf',
        checked: false,
        id:123,
        children: [
            {
                value: '/AG_TURF-123/TRACTOR-456',
                label: 'Tractors',
                checked: false,
                id:456,
                children: [
                    {
                        value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series',
                        label: 'Large (7, 8, 9) Series',
                        checked: false,
                        id:789,
                        children: [{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor',
                            label: '7 Family Tractor',
                            checked: false,
                            id:101112
                        },{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor',
                            label: '8 Family Tractor',
                            checked: false,
                            id:131415
                        },{
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor',
                            label: '9 Family Tractor',
                            checked: false,
                            id:161718
                        }],
                    },
                    {
                        value: '/app/Http/routes.js',
                        label: 'routes.js',
                        checked: false,
                        id:181920
                    },
                ],
            },
            {
                value: '/app/Providers',
                label: 'Providers',
                checked: false,
                id:212223,
                children: [{
                    value: '/app/Http/Providers/EventServiceProvider.js',
                    label: 'EventServiceProvider.js',
                    checked: false,
                    id:242526
                }],
            },
        ],
    },
    {
        value: '/config',
        label: 'config',
        checked: false,
        id:272829,
        children: [
            {
                value: '/config/app.js',
                label: 'app.js',
                checked: false,
                id:303132
            },
            {
                value: '/config/database.js',
                label: 'database.js',
                checked: false,
                id:333435
            },
        ],
    },
    {
        value: '/public',
        label: 'public',
        checked: false,
        id:353637,
        children: [
            {
                value: '/public/assets/',
                label: 'assets',
                checked: false,
                id:383940,
                children: [{
                    value: '/public/assets/style.css',
                    label: 'style.css',checked: false,
                    id:404142
                }],
            },
            {
                value: '/public/index.html',
                label: 'index.html',
                checked: false,
                id: 434445
            },
        ],
    },
    {
        value: '/.env',
        label: '.env',
        checked: false,
        id: 464748
    },
    {
        value: '/.gitignore',
        label: '.gitignore',
        checked: false,
        id: 495051
    },
    {
        value: '/README.md',
        label: 'README.md',
        checked: false,
        id: 525354
    },
];

This is my list of value :

const ids=[525354,123,131415];

I want to set checked to true if id matched. My main array may go to 6 to 7 step deep.

What I've done till yet :

setCheckedFlagToItems(checkList, items) {
        return items.map((item) => {
            const node = item;
            if (checkList.indexOf(node.id) !== -1) {
                node.checked = true;
            }
            if ((node.children) && (Array.isArray(node.children) && node.children.length > 0)) {
                this.setCheckedFlagToItems(checkList, node.children);
            }
            return node;
        }, this);
    }

But it not working as usual.

like image 819
Hashir Hussain Avatar asked Apr 25 '17 13:04

Hashir Hussain


People also ask

How do I update nested objects?

To update nested properties in a state object in React: Pass a function to setState to get access to the current state object. Use the spread syntax (...) to create a shallow copy of the object and the nested properties. Override the properties you need to update.

How do you replace values in an array of objects?

To change the value of an object in an array:Call the findIndex() method to get the index of the specific object. Access the array at the index and change the property's value using dot notation. The value of the object in the array will get updated in place.

How do I update a nested array in Mongodb?

Update Nested Arrays in Conjunction with $[]The $[<identifier>] filtered positional operator, in conjunction with the $[] all positional operator, can be used to update nested arrays. The following updates the values that are greater than or equal to 8 in the nested grades. questions array if the associated grades.

How do you modify a value in an array?

To change the value of all elements in an array:Use the forEach() method to iterate over the array. The method takes a function that gets invoked with the array element, its index and the array itself. Use the index of the current iteration to change the corresponding array element.


2 Answers

You could use an iterative and recursice approach with a named function as callback for Array#forEach.

let mainArray = [
{
    value: '/AG_TURF-123', 
    label: 'Ag & Turf', 
    checked: false, 
    id: 123, 
    children: [
        { 
            value: '/AG_TURF-123/TRACTOR-456', 
            label: 'Tractors', 
            checked: false, 
            id: 456, 
            children: [
                { 
                    value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series', 
                    label: 'Large (7, 8, 9) Series', 
                    checked: false, 
                    id: 789, 
                    children: [
                        { 
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor', 
                            label: '7 Family Tractor', 
                            checked: false, 
                            id: 101112 
                        }, 
                        { 
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor', 
                            label: '8 Family Tractor', 
                            checked: false, 
                            id: 131415 
                        }, 
                        { 
                            value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor', 
                            label: '9 Family Tractor', 
                            checked: false, 
                            id: 161718 
                        }
                    ] 
                }, 
                {
                    value: '/app/Http/routes.js', 
                    label: 'routes.js', 
                    checked: false, 
                    id: 181920 
                }
            ]
        }, 
        { 
            value: '/app/Providers', 
            label: 'Providers', 
            checked: false, 
            id: 212223, 
            children: [
                { 
                    value: '/app/Http/Providers/EventServiceProvider.js', 
                    label: 'EventServiceProvider.js', 
                    checked: false, 
                    id: 242526 
                }
            ]
        }
    ]
}, 
{
    value: '/config', 
    label: 'config', 
    checked: false, 
    id: 272829, 
    children: [
        {
            value: '/config/app.js', 
            label: 'app.js', 
            checked: false, 
            id: 303132
        },
        {
            value: '/config/database.js', 
            label: 'database.js', 
            checked: false, 
            id: 333435 
        }
    ]
}, 
{
    value: '/public', 
    label: 'public', 
    checked: false, 
    id: 353637, 
    children: [
        {
            value: '/public/assets/', 
            label: 'assets', 
            checked: false, 
            id: 383940, 
            children: [
                {
                    value: '/public/assets/style.css', 
                    label: 'style.css', 
                    checked: false, 
                    id: 404142
                }
            ]
        }, 
        {
            value: '/public/index.html', 
            label: 'index.html', 
            checked: false, 
            id: 434445 
        }
    ] 
}, 
{ 
    value: '/.env', 
    label: '.env', 
    checked: false, 
    id: 464748 
}, 
{ 
    value: '/.gitignore', 
    label: '.gitignore', 
    checked: false, 
    id: 495051 
}, 
{ 
    value: '/README.md', 
    label: 'README.md', 
    checked: false, 
    id: 525354 
}
],
    ids = [525354, 123, 131415];

mainArray
    .forEach(
        function iter(a) {
            if (ids.includes(a.id)) {
                a.checked = true;
            }
            Array.isArray(a.children) && a.children.forEach(iter);
        }
    );

console.log(mainArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
like image 56
Nina Scholz Avatar answered Oct 21 '22 08:10

Nina Scholz


If your ids are "unique" (there's only one unique object for each id property), you could also split this action in to two steps:

  1. Make a new data structure that flattens all items in to one object of id: item
  2. Loop through the ids to retrieve the items from this object.

If you find yourself looking up many objects by id, it might be easier to create this interim representation.

The creation of the map uses recursion similar to the other answer: whenever an item contains a children array, it adds those to the map object before it returns.

const mainArray = [{ value: '/AG_TURF-123', label: 'Ag & Turf', checked: false, id: 123, children: [{ value: '/AG_TURF-123/TRACTOR-456', label: 'Tractors', checked: false, id: 456, children: [{ value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series', label: 'Large (7, 8, 9) Series', checked: false, id: 789, children: [{ value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/7-family-tractor', label: '7 Family Tractor', checked: false, id: 101112 }, { value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/8-family-tractor', label: '8 Family Tractor', checked: false, id: 131415 }, { value: '/AG_TURF-123/TRACTOR-456/Large-7-8-9-series/9-family-tractor', label: '9 Family Tractor', checked: false, id: 161718 }] }, { value: '/app/Http/routes.js', label: 'routes.js', checked: false, id: 181920 }] }, { value: '/app/Providers', label: 'Providers', checked: false, id: 212223, children: [{ value: '/app/Http/Providers/EventServiceProvider.js', label: 'EventServiceProvider.js', checked: false, id: 242526 }] }] }, { value: '/config', label: 'config', checked: false, id: 272829, children: [{ value: '/config/app.js', label: 'app.js', checked: false, id: 303132 }, { value: '/config/database.js', label: 'database.js', checked: false, id: 333435 }] }, { value: '/public', label: 'public', checked: false, id: 353637, children: [{ value: '/public/assets/', label: 'assets', checked: false, id: 383940, children: [{ value: '/public/assets/style.css', label: 'style.css', checked: false, id: 404142 }] }, { value: '/public/index.html', label: 'index.html', checked: false, id: 434445 }] }, { value: '/.env', label: '.env', checked: false, id: 464748 }, { value: '/.gitignore', label: '.gitignore', checked: false, id: 495051 }, { value: '/README.md', label: 'README.md', checked: false, id: 525354 }];

// We reduce the array of nested items in to one object of:
// { id: item }
const idMap = mainArray.reduce(function merge(map, node) {
  map[node.id] = node;
  
  if (Array.isArray(node.children)) {
    node.children.reduce(merge, map);
  }
  
  return map;
}, {});

const ids = [525354, 123, 131415];

// Whenever you need an item, you can get it
// using idMap[id]
const items = ids.map(id => idMap[id]);
items.forEach(item => item.checked = true);

// or: ids.forEach(id => idMap[id].checked = true)
like image 41
user3297291 Avatar answered Oct 21 '22 08:10

user3297291