Skip to content

Adding Nodes

Note

Adding a node is a data write operation and must be performed inside the write method.

Creating the Root Node

You can create the root node with the createRoot method.

ts

import { FlexTreeManager } from 'flextree';
const tree = new FlexTreeManager("tree",{...})

// Must be executed inside the write method, otherwise an exception is thrown
await tree.write(async ()=>{ 
    await tree.createRoot({    // Create the root node
        name:"Root",
        // .... other node properties    
    })  
})
  • The createRoot method must be executed inside the write method, otherwise an exception is thrown.
  • A tree can only have one root node. Calling createRoot again will throw an exception.

Adding Nodes

Once a FlexTreeManager is created, you can use the addNodes method to add one or more nodes.

ts
async addNodes(
    nodes: Partial<TreeNode>[], 
    atNode?: NodeId | TreeNode | null, 
    pos: FlexNodeRelPosition = FlexNodeRelPosition.LastChild
):void

enum FlexNodeRelPosition {
    LastChild = 0,
    FirstChild = 1,
    NextSibling = 2,
    PreviousSibling = 3,
}
  • Parameters
Parameter Type Default Description
nodes Partial<TreeNode>[] None Array of node objects
atNode NodeId | TreeNode null Optional. Specifies under which node to add
pos FlexNodeRelPosition FlexNodeRelPosition.LastChild Optional. Add position

Nested Batch Adding

Besides accepting a flat array of nodes, addNodes also supports a nested structure — passing a complete subtree in a single call and describing the parent-child relationships via the children field. In this case the options object form is recommended:

ts
async addNodes(
    nodes: FlexTreeNodeInput[],
    options?: {
        at?: NodeId | TreeNode | null   // Parent node; defaults to the root node
        pos?: FlexNodeRelPosition       // Add position; defaults to LastChild
        childrenField?: string          // Child field name; defaults to 'children'
    }
): Promise<void>
  • Example
ts
await tree.write(async () => {
    await tree.addNodes([
        {
            name: "A",
            children: [            // Children of A
                { name: "A1" },
                { name: "A2" },
            ],
        },
        {
            name: "B",
            children: [
                { name: "B1" },
            ],
        },
    ])
})

The generated tree structure is as follows:

  • Root
    • A
      • A1
      • A2
    • B
      • B1
  • Notes

    • The children field in the nested structure is only used to describe the hierarchy at the time of adding; it is not written to the database (the hierarchy is maintained through left/right values in the database).
    • The default child field name is children. It can be customized via options.childrenField (for example, when some data sources use field names like subs or child).

Last Child

Adds one or more nodes as the last child of the atNode node.

ts
import { FlexTreeManager } from 'flextree';
const tree = new FlexTreeManager("tree",{...})

await tree.write(async ()=>{  
    // Create the root node
    await tree.createRoot({name:"Root"}) 
    // Add nodes under the root node
    await tree.addNodes([
        {name: "A"},   
        {name: "B"},
        {name: "C"},
    ])
})

The generated tree structure is as follows:

  • Root
    • +A
    • +B
    • +C

In the example above, we added three child nodes under the root node (omitting the atNode and pos parameters).

Next we add two child nodes under node A.

ts
import { LastChild } from "flextree"

await tree.write(async ()=>{ 
    const anode = await tree.findNode({name:"A"})
    // Add nodes under the root node
    await tree.addNodes([
        {name: "A1"},
        {name: "A2"}
    ],anode,LastChild)  
})

The generated tree structure is as follows:

  • Root
    • A
      • +A1
      • +A2
    • B
    • C

First Child

Adds one or more nodes as the first child of the atNode node.

ts

import { FirstChild } from "flextree"

await tree.write(async ()=>{   
    const anode = await tree.findNode({name:"A"})
    // 1st add
    await tree.addNodes([
        {name: "A1"},
    ],anode,FirstChild)
    // 2nd add
    await tree.addNodes([
        {name: "A2"},
    ],anode,FirstChild)
    // 3rd add
    await tree.addNodes([
        {name: "A3"},
    ],anode,FirstChild)
})

The generated tree structure is as follows:

  • Root
    • A atNode
      • +A3 3rd add
      • +A2 2nd add
      • +A1 1st add
    • B
    • C

Next Sibling

Adds one or more nodes as the next sibling of the atNode node.

ts

import { NextSibling } from "flextree"

await tree.write(async ()=>{   
    const anode = await tree.findNode({name:"A"})
    // 1st add
    await tree.addNodes([
        {name: "A1"},
    ],anode,NextSibling)
    // 2nd add
    await tree.addNodes([
        {name: "A2"},
    ],anode,NextSibling)
    // 3rd add
    await tree.addNodes([
        {name: "A3"},
    ],anode,NextSibling)
})

The generated tree structure is as follows:

  • Root
    • A atNode
    • +A3 3rd add
    • +A2 2nd add
    • +A1 1st add
    • B
    • C

Previous Sibling

Adds one or more nodes as the previous sibling of the atNode node.

ts

import { PreviousSibling } from "flextree"

await tree.write(async ()=>{   
    const anode = await tree.findNode({name:"A"})
    // 1st add
    await tree.addNodes([
        {name: "A1"},
    ],anode,PreviousSibling)
    // 2nd add
    await tree.addNodes([
        {name: "A2"},
    ],anode,PreviousSibling)
    // 3rd add
    await tree.addNodes([
        {name: "A3"},
    ],anode,PreviousSibling)
})

The generated tree structure is as follows:

  • Root
    • +A1 1st add
    • +A2 2nd add
    • +A3 3rd add
    • A atNode
    • B
    • C