Node manipulation in Vue TreeView component

23 Dec 202424 minutes to read

The TreeView component provides essential methods for dynamically managing nodes, offering the ability to create a highly interactive and customizable tree structure.

These methods provide the flexibility to add, remove, update, refresh, or relocate nodes as needed, facilitating a fully interactive and customizable TreeView structure.

Dynamically adding nodes

The addNodes method allows you to insert new nodes at designated positions within the TreeView by passing the necessary node information. You can add both parent and child nodes by specifying their target ID.

<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview"  :fields="fields"></ejs-treeview>
        </div>
        <div id="btn">
            <ejs-button id="button1" ref="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Add parent"></ejs-button>
            <ejs-button id="button2" ref="button2" cssClass="e-primary inline-element right" v-on:click="btnClick2" content="Add child"></ejs-button>        
        </div>
    </div>
</template>

<script setup>

    import { TreeViewComponent as EjsTreeview } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    const treeViewInstance = ref(null);
    var dataSource = [
        { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Child 1' },
        { id: 3, pid: 1, name: 'Child 2' },
        { id: 4, pid: 1, name: 'Child 3' },
        { id: 7, name: 'Parent 2', hasChild: true },
        { id: 8, pid: 7, name: 'Child 1' },
        { id: 9, pid: 7, name: 'Child 2' },
        { id: 10, pid: 7, name: 'Child 3' },
    ];

    const fields = { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' };

    const btnClick1 = () => {
        treeViewInstance.addNodes([
            { id: 12, name: 'New Parent' },
            { id: 13, pid: 12, name: 'New Child1' },
        ]);
    };
    const btnClick2 = () => {
        treeViewInstance.addNodes([{ id: 11, name: 'New Child2', pid: 1 }], '1', null);
    };
</script>
<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn{
            margin-left: 50px;
            margin-top: 20px;
        }
</style>
<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview"  :fields="fields"></ejs-treeview>
        </div>
        <div id="btn">
            <ejs-button id="button1" ref="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Add parent"></ejs-button>
            <ejs-button id="button2" ref="button2" cssClass="e-primary inline-element right" v-on:click="btnClick2" content="Add child"></ejs-button>        
        </div>
    </div>
</template>

<script>
    import { TreeViewComponent } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    export default {
        name: "App",
        components: {
            "ejs-treeview": TreeViewComponent,
            "ejs-button": ButtonComponent
        },
        data() {
            let dataSource = [
                { id: 1, name: 'Discover Music', hasChild: true, expanded: true },
                { id: 2, pid: 1, name: 'Hot Singles' },
                { id: 3, pid: 1, name: 'Rising Artists' },
                { id: 4, pid: 1, name: 'Live Music' },
                { id: 6, pid: 1, name: 'Best of 2017 So Far' },
                { id: 7, name: 'Sales and Events', hasChild: true },
                { id: 8, pid: 7, name: '100 Albums - $5 Each' },
                { id: 9, pid: 7, name: 'Hip-Hop and R&B Sale' },
                { id: 10, pid: 7, name: 'CD Deals' },
                { id: 11, name: 'Categories', hasChild: true },
                { id: 12, pid: 11, name: 'Songs' },
                { id: 13, pid: 11, name: 'Bestselling Albums' },
                { id: 14, pid: 11, name: 'New Releases' },
                { id: 15, pid: 11, name: 'Bestselling Songs' },
                { id: 16, name: 'MP3 Albums', hasChild: true },
                { id: 17, pid: 16, name: 'Rock' },
                { id: 18, pid: 16, name: 'Gospel' },
                { id: 19, pid: 16, name: 'Latin Music' },
                { id: 20, pid: 16, name: 'Jazz' },
                { id: 21, name: 'More in Music', hasChild: true },
                { id: 22, pid: 21, name: 'Music Trade-In' },
                { id: 23, pid: 21, name: 'Redeem a Gift Card' },
                { id: 24, pid: 21, name: 'Band T-Shirts' },
            ];
            return {
                fields: { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' },
            };
        },
        methods: {
            btnClick1: function () {
                this.$refs.treeview.addNodes([
                    { id: 12, name: 'New Parent' },
                    { id: 13, pid: 12, name: 'New Child1' },
                ]);
            },
            btnClick2: function () {
                this.$refs.treeview.addNodes([{ id: 11, name: 'New Child2', pid: 1 }], '1', null);
            },
        }
    }
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn{
            margin-left: 50px;
            margin-top: 20px;
        }
</style>

Dynamically removing nodes

The TreeView removeNodes method lets you remove multiple nodes by providing their IDs. You can remove both parent and child nodes.

<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview"  :fields="fields"></ejs-treeview>
        </div>
        <div id="btn">
            <ejs-button id="button1" ref="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Remove parent"></ejs-button>
            <ejs-button id="button2" ref="button2" cssClass="e-primary inline-element right" v-on:click="btnClick2" content="Remove child"></ejs-button>        
        </div>
    </div>
</template>

<script setup>

    import { TreeViewComponent as EjsTreeview } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    const treeViewInstance = ref(null);
    var dataSource = [
        { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Child 1' },
        { id: 3, pid: 1, name: 'Child 2' },
        { id: 4, pid: 1, name: 'Child 3' },
        { id: 7, name: 'Parent 2', hasChild: true },
        { id: 8, pid: 7, name: 'Child 1' },
        { id: 9, pid: 7, name: 'Child 2' },
        { id: 10, pid: 7, name: 'Child 3' },
    ];

    const fields = { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' };

    const btnClick1 = () => {
        treeViewInstance.removeNodes(['7']);
    };
    const btnClick2 = () => {
        treeViewInstance.removeNodes(['3','4']);
    };
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn {
        margin-left: 50px;
        margin-top: 20px;
    }
</style>
<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview" :fields="fields" >                
            </ejs-treeview></div>
            <div id="btn">
            <ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Remove parent"></ejs-button>
            <ejs-button id="button2" cssClass="e-primary inline-element right" v-on:click="btnClick2" content="Remove child"></ejs-button>        
        </div>
    </div>
</template>

<script>
    import { TreeViewComponent } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    export default {
        name: "App",
        components: {
            "ejs-treeview": TreeViewComponent,
            "ejs-button": ButtonComponent
        },
        data() {
            var dataSource = [
                { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
                { id: 2, pid: 1, name: 'Child 1' },
                { id: 3, pid: 1, name: 'Child 2' },
                { id: 4, pid: 1, name: 'Child 3' },
                { id: 7, name: 'Parent 2', hasChild: true },
                { id: 8, pid: 7, name: 'Child 1' },
                { id: 9, pid: 7, name: 'Child 2' },
                { id: 10, pid: 7, name: 'Child 3' },
            ];
            return {
                fields: { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' },
            }
        },
        methods: {
            btnClick1: function () {
                this.$refs.treeview.removeNodes(['7']);
            },
            btnClick2: function () {
                this.$refs.treeview.removeNodes(['3','4']);
            },
        }
    }
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }

    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>

Dynamically update nodes

The TreeView component has the updateNode method, which allows you to change a specific node’s text by providing its target (either the node ID or element) and the new text. To enable text editing, set the allowEditing property to true, ensuring the correct functionality of the updateNode method.

<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeViewInstance" :fields="fields" :allowEditing='true'></ejs-treeview> 
        </div>
        <div id="btn"><ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Update node"></ejs-button></div>
    </div>
</template>

<script setup>

    import { TreeViewComponent as EjsTreeview } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    const treeViewInstance = ref(null);
    var dataSource = [
        { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Child 1' },
        { id: 3, pid: 1, name: 'Child 2' },
        { id: 4, pid: 1, name: 'Child 3' },
        { id: 7, name: 'Parent 2', hasChild: true },
        { id: 8, pid: 7, name: 'Child 1' },
        { id: 9, pid: 7, name: 'Child 2' },
        { id: 10, pid: 7, name: 'Child 3' },
    ];

    const fields = { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' };

    const btnClick1 = () => {
        treeViewInstance.updateNode('4', 'Node updated');
    };

</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>
<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview" :fields="fields" :allowEditing='true'></ejs-treeview>
        </div>
        <div id="btn">
            <ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Update node"></ejs-button>
        </div>
    </div>
</template>

<script>
    import { TreeViewComponent } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    export default {
        name: "App",
        components: {
            "ejs-treeview": TreeViewComponent,
            "ejs-button": ButtonComponent
        },
        data() {
            var dataSource = [
                { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
                { id: 2, pid: 1, name: 'Child 1' },
                { id: 3, pid: 1, name: 'Child 2' },
                { id: 4, pid: 1, name: 'Child 3' },
                { id: 7, name: 'Parent 2', hasChild: true },
                { id: 8, pid: 7, name: 'Child 1' },
                { id: 9, pid: 7, name: 'Child 2' },
                { id: 10, pid: 7, name: 'Child 3' },
            ];
            return {
                fields: { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' },            
            }
        },
        methods: {
            btnClick1: function () {
                this.$refs.treeview.updateNode('4', 'Node updated');
            },
        }
    }
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>

Dynamically refresh nodes

The refreshNode method in TreeView allows you to update the content of a specific node by providing its target and the new details. To retrieve the current details of the node, use the getTreeData method in conjunction with the node’s ID. This method refreshes a designated node within the TreeView.

<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeViewInstance" :fields="fields" ></ejs-treeview>
        </div>
        <div id="btn">
            <ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Refresh node"></ejs-button>
        <div>
    </div>
</template>

<script setup>

    import { TreeViewComponent as EjsTreeview } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    const treeViewInstance = ref(null);

    var dataSource = [
        { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Child 1' },
        { id: 3, pid: 1, name: 'Child 2' },
        { id: 4, pid: 1, name: 'Child 3' },
        { id: 7, name: 'Parent 2', hasChild: true, expanded: true },
        { id: 8, pid: 7, name: 'Child 1' },
        { id: 9, pid: 7, name: 'Child 2' },
        { id: 10, pid: 7, name: 'Child 3' },
    ];

    const fields = { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' };

    const btnClick1 = () => {
        var nodeData = treeViewInstance.getTreeData('4');
        nodeData[0].name = 'Node refreshed';
        treeViewInstance.refreshNode('4', nodeData);
    };
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    
    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>
<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview" :fields="fields"></ejs-treeview>
            </div>
            <div id="btn">
                <ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Refresh node"></ejs-button>
            <div>
    </div>
</template>

<script>
    import { TreeViewComponent } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    export default {
        name: "App",
        components: {
            "ejs-treeview": TreeViewComponent,
            "ejs-button": ButtonComponent
        },
        data() {
            
            var dataSource = [
                { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
                { id: 2, pid: 1, name: 'Child 1' },
                { id: 3, pid: 1, name: 'Child 2' },
                { id: 4, pid: 1, name: 'Child 3' },
                { id: 7, name: 'Parent 2', hasChild: true, expanded: true },
                { id: 8, pid: 7, name: 'Child 1' },
                { id: 9, pid: 7, name: 'Child 2' },
                { id: 10, pid: 7, name: 'Child 3' },
            ];
            return {
                fields : { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' },                    
            }
        },
        methods: {
            btnClick1: function () {
                var nodeData = this.$refs.treeview.getTreeData('4');
                nodeData[0].name = 'Node refreshed';
                this.$refs.treeview.refreshNode('4', nodeData);
            },
        }
    }
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }

    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>

Dynamically move nodes

The moveNodes method in TreeView allows you to relocate a node by defining the node to be moved, the target location, and the index within that target. It facilitates the repositioning of nodes within the same TreeView based on the specified target.

<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeViewInstance" :fields="fields" ></ejs-treeview>
        </div>
        <div id="btn">
            <ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Move node"></ejs-button>
        </div>
    </div>
</template>

<script setup>

    import { TreeViewComponent as EjsTreeview } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    const treeViewInstance = ref(null);
    var dataSource = [
        { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
        { id: 2, pid: 1, name: 'Child 1' },
        { id: 3, pid: 1, name: 'Child 2' },
        { id: 4, pid: 1, name: 'Child 3' },
        { id: 7, name: 'Parent 2', hasChild: true },
        { id: 8, pid: 7, name: 'Child 1' },
        { id: 9, pid: 7, name: 'Child 2' },
        { id: 10, pid: 7, name: 'Child 3' },
    ];

    const fields = { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' };

    const btnClick1 = () => {
        treeViewInstance.moveNodes(['2'], '3', 1); 
    };
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>
<template>
    <div id="app">
        <div class="control_wrapper">
            <ejs-treeview id='treeview' ref="treeview" :fields="fields" ></ejs-treeview></div>
        <div id="btn">
            <ejs-button id="button1" cssClass="e-primary inline-element right" v-on:click="btnClick1" content="Move node"></ejs-button>
        </div>
    </div>
</template>

<script>
    import { TreeViewComponent } from "@syncfusion/ej2-vue-navigations";
    import { ButtonComponent } from '@syncfusion/ej2-vue-buttons';

    export default {
        name: "App",
        components: {
            "ejs-treeview": TreeViewComponent,
            "ejs-button": ButtonComponent
        },
        data() {
            var dataSource = [
                { id: 1, name: 'Parent 1', hasChild: true, expanded: true },
                { id: 2, pid: 1, name: 'Child 1' },
                { id: 3, pid: 1, name: 'Child 2' },
                { id: 4, pid: 1, name: 'Child 3' },
                { id: 7, name: 'Parent 2', hasChild: true },
                { id: 8, pid: 7, name: 'Child 1' },
                { id: 9, pid: 7, name: 'Child 2' },
                { id: 10, pid: 7, name: 'Child 3' },
            ];
            return {
                fields: { dataSource: dataSource, id: 'id', parentID: 'pid', text: 'name',  hasChildren: 'hasChild' },
            }
        },
        methods: {
            btnClick1: function () {
                this.$refs.treeview.moveNodes(['2'], '3', 1);
            },
        }
    }
</script>

<style>
    @import "../node_modules/@syncfusion/ej2-base/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-navigations/styles/material.css";
    @import "../node_modules/@syncfusion/ej2-vue-buttons/styles/material.css";

    .control_wrapper {
        display: block;
        max-width: 400px;
        max-height: 320px;
        margin: auto;
        overflow: auto;
        border: 1px solid #dddddd;
        border-radius: 3px;
    }

    #app {
        width: 350px;
        margin: 0 auto;
    }
    #btn{
        margin-left: 50px;
        margin-top: 20px;
    }
</style>