So I have this list of nested objects that I'm supposed to show in a web interface,
The nesting can go up to 4 levels deep
I need to filter it based on an object property (let's say owner_id
).
The filter should recursively return parents if a child is nested inside while checking if it's a target object: set a property .filtered=true
to it, if it is a parent: let's say we set parent=true
to it.
The display depends on those properties in order to expand or collapse parents and highlight filtered ones using a different color
(Quick side note: everything has an id, and I have access to a flat version of the objects array without nesting)
My objects structure:
let objs =
[
{
title: 'title.1',
owner_id: 1
child_cards: [
{
title: 'title.1.1',
owner_id: 2
child_cards: [
{
title: 'title.1.1.1',
owner_id: 1,
},
{
title: 'title.1.1.2',
owner_id: 2
},
]
},
{
title: 'title.1.2',
owner_id: 2,
child_cards: [
{
title: 'title.1.2.1',
owner_id: 1,
},
]
},
]
},
{
title: 'title.2',
owner_id: 3
child_cards: [
{
title: 'title.2.1',
owner_id: 2
}
]
},
{
title: 'title.3',
owner_id: 1,
child_cards: [
{
title: 'title.3.1',
owner_id: 1
},
{
title: 'title.3.2',
owner_id: 1
},
{
title: 'title.3.3',
owner_id: 1
}
]
}
]
Example calling it with owner_id=2:
[
{
title: 'title.1',
owner_id: 1,
parented: true,
child_cards: [
{
title: 'title.1.1',
owner_id: 2,
parented: true,
filtered: true,
child_cards: [
{
title: 'title.1.1.2',
owner_id: 2,
filtered: true
},
]
},
{
title: 'title.1.2',
owner_id: 2,
filtered: true,
child_cards: [
{
title: 'title.1.2.1',
owner_id: 1,
},
]
},
]
},
{
title: 'title.2',
owner_id: 3,
parented: true,
child_cards: [
{
title: 'title.2.1',
owner_id: 2,
filtered: true
}
]
}
]
Somehow every solution I found on StackOverflow doesn't include my case where I need to set specific properties to children/parents or the algorithm instantly ignores any other child if it only finds one occurrence.
Any help is appreciated! 😁
I think this function solves the problem:
const source =
[
{
title: 'title.1',
owner_id: 1,
child_cards: [
{
title: 'title.1.1',
owner_id: 2,
child_cards: [
{
title: 'title.1.1.1',
owner_id: 1,
},
{
title: 'title.1.1.2',
owner_id: 2
},
]
},
{
title: 'title.1.2',
owner_id: 2,
child_cards: [
{
title: 'title.1.2.1',
owner_id: 1,
},
]
},
]
},
{
title: 'title.2',
owner_id: 3,
child_cards: [
{
title: 'title.2.1',
owner_id: 2
}
]
},
{
title: 'title.3',
owner_id: 1,
child_cards: [
{
title: 'title.3.1',
owner_id: 1
},
{
title: 'title.3.2',
owner_id: 1
},
{
title: 'title.3.3',
owner_id: 1
}
]
}
]
const treatNode = (node, name, value) => {
const filtered = node[name] == value
const children = node.child_cards ? node.child_cards.map(x => treatNode(x, name, value)) : [];
const filtered_children = children.filter(x => x.filtered || x.parent);
const parent = filtered_children.length > 0;
let ret = {...node};
delete ret.child_cards;
if (filtered) ret = {...ret, filtered: true};
if (parent) ret = {...ret, parent: true};
if (filtered_children.length > 0)
ret = {...ret, child_cards: filtered_children};
return ret;
}
console.log(source.map(x => treatNode(x, "owner_id", 2)).filter(x => x.filtered || x.parent))
Please let me know if is it what you are looking for.