tree-handler is a module to easily manipulate tree structures.
import treeHandler from 'tree-handler';
const model = {
id: 'root',
children: [
{ id: 'A', children: [] },
{ id: 'B', children: [] },
],
};
const tree = treeHandler.parse(model);
import treeHandler from 'tree-handler';
const model = {
id: 'root',
subtasks: [
{ id: 'A', subtasks: [] },
{ id: 'B', subtasks: [] },
],
};
const tree = treeHandler.parse(model, { childrenProperty: 'subtasks' });
tree.findOne((node) => node.model.id === 'A');
tree.find((node) => node.model.type === 'cake');
tree.addChild({ id: '123', type: 'chocolate', children: [] });
const newNode = treeHandler.parse({
id: '123',
type: 'chocolate',
children: [],
});
tree.addChild(newNode);
const node = tree.findOne((node) => node.model.id === 'A');
node.delete();
const modelA = {
id: 'A',
children: [
{ id: 'B', children: [{ id: 'B1', children: [] }] },
{
id: 'C',
children: [
{ id: 'C1', children: [] },
{ id: 'C2', children: [] },
],
},
],
};
const tree = treeHandler.parse(modelA);
tree.moveUnderParnet({
node: (node) => node.model.id === 'B1',
toParent: (node) => node.model.id === 'C',
atIndex: 1,
});
tree.moveToSibling({
node: (node) => node.model.id === 'B1',
toSibling: (node) => node.model.id === 'C2',
at: 'BEFORE', // options: BEFORE, AFTER
});
the filter function will return to us new TreeNode classes based on the filter conditions. There are two modes to filter a tree structure.
this one is the "expected" way of filtering a tree structure's nodes. If a node should be filtered out, then that node along its children will be removed.
const dataTree = {
id: '1',
tag: 'pending',
subtasks: [
{
id: '2',
tag: 'pending',
subtasks: [
{ id: '4', tag: 'complete', subtasks: [] },
{ id: '46', tag: 'in progress', subtasks: [] },
],
},
{
id: '3',
tag: 'in progress',
subtasks: [
{
id: '4',
tag: 'pending',
subtasks: [
{
id: '6',
tag: 'complete',
subtasks: [
{
id: '10',
tag: 'pending',
subtasks: [{ id: '11', tag: 'complete', subtasks: [] }],
},
],
},
{
id: '7',
tag: 'complete',
subtasks: [{ id: '74', tag: 'in progress', subtasks: [] }],
},
],
},
{ id: '5', tag: 'pending', subtasks: [] },
],
},
{ id: '4', tag: 'complete', subtasks: [] },
],
};
const tree = treeHandler.parse(dataTree, {
childrenProperty: 'subtasks',
});
const newTree = tree.filter((node) => node.tag !== 'in progress');
console.log(newTree);
result:
{
id: '1',
tag: 'pending',
subtasks: [
{
id: '2',
tag: 'pending',
subtasks: [{ id: '4', tag: 'complete', subtasks: [] }],
},
{ id: '4', tag: 'complete', subtasks: [] },
],
};
this filtering method is unique. What it does is that it filtering out each node indiviually. Meaning if a node should be filtered out, and if it has children that should not be filtered out, then those children will be moved to the same depth level and starting index number of their parent.
const dataTree = {
id: '1',
tag: 'pending',
subtasks: [
{ id: '2', tag: 'pending', subtasks: [] },
{
id: '3',
tag: 'in progress',
subtasks: [
{
id: '4',
tag: 'pending',
subtasks: [
{
id: '6',
tag: 'complete',
subtasks: [
{
id: '10',
tag: 'pending',
subtasks: [{ id: '10', tag: 'complete', subtasks: [] }],
},
],
},
{ id: '7', tag: 'complete', subtasks: [] },
],
},
{ id: '5', tag: 'pending', subtasks: [] },
],
},
{ id: '4', tag: 'complete', subtasks: [] },
],
};
const treeResult =
const tree = treeHandler.parse(dataTree, { childrenProperty: 'subtasks' });
const newTrees = tree.filter(
(node) => node.tag !== 'in progress',
'mergeChildren'
);
console.log(newTrees)
result:
[
{
id: '1',
tag: 'pending',
subtasks: [
{ id: '2', tag: 'pending', subtasks: [] },
{
id: '4',
tag: 'pending',
subtasks: [
{
id: '6',
tag: 'complete',
subtasks: [
{
id: '10',
tag: 'pending',
subtasks: [{ id: '10', tag: 'complete', subtasks: [] }],
},
],
},
{ id: '7', tag: 'complete', subtasks: [] },
],
},
{ id: '5', tag: 'pending', subtasks: [] },
{ id: '4', tag: 'complete', subtasks: [] },
],
},
];
tree.flatten();
tree.forEach((node) => {
console.log(node);
});
Heavily inspired by tree-model