javascriptvue.jsztree

How to update a tree without refreshing whole page?


I'm creating web application with zTree. The tree is built based on data from the Golang backend. Tree leaves change custom icons while the application is running. How to change icons, based on backend data, without refreshing the page?

With http-equiv="refresh" page is blinking and lost focus. Here is working but blinking sample with zTree and refresh (I cut of backend part for simplicity):

<HTML>
<HEAD>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta http-equiv="refresh" content="5">
    <link rel="stylesheet" href="../static/css/zTreeStyle/zTreeStyle.css" type="text/css">
    <script type="text/javascript" src="../static/js/jquery-1.4.4.min.js"></script>
    <script type="text/javascript" src="../static/js/jquery.ztree.core.js"></script>
</HEAD>

<BODY>
    <div id="app">
        <TABLE>
            <TR>
                <TD width=260px valign=top>
                    <ul id="tree" class="ztree"></ul>
                </TD>
                <TD valign=top>
                    <p>Some text</p>
                </TD>
            </TR>
        </TABLE>
        
        <SCRIPT type="text/javascript">
            var zTree;
            var setting = {
                data: {
                    simpleData: {
                    enable: true,
                    idKey: "id",
                    pIdKey: "pId",
                    rootPId: ""
                    }
                }
            };
            var zNodes = [
                {id: 1, pId: 0, name: "root", icon:"../static/css/zTreeStyle/img/diy/c16green.png"},
                {id: 2, pId: 1, name: "leaf", icon:"../static/css/zTreeStyle/img/diy/c16red.png"},
            ];
            $(document).ready(function () {
                var t = $("#tree");
                t = $.fn.zTree.init(t, setting, zNodes);
            });
        </script>
    </div>
</BODY>
</HTML>

I try to use Vue.js, but cannot bind data to zTree. Here is not working sample with Vue.js data binding inside script tag:

<HTML>
<HEAD>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link rel="stylesheet" href="../static/css/zTreeStyle/zTreeStyle.css" type="text/css">
    <script type="text/javascript" src="../static/js/jquery-1.4.4.min.js"></script>
    <script type="text/javascript" src="../static/js/jquery.ztree.core.js"></script>
    <script src="https://unpkg.com/vue"></script>
</HEAD>

<BODY>
    <div id="app">
        <TABLE>
            <TR>
                <TD width=260px valign=top>
                    <ul id="tree" class="ztree"></ul>
                </TD>
                <TD valign=top>
                    <p>{{ now }}</p>
                    <p>Some text</p>
                </TD>
            </TR>
        </TABLE>
        
        <SCRIPT type="text/javascript">
            var zTree;
            var setting = {
                data: {
                    simpleData: {
                    enable: true,
                    idKey: "id",
                    pIdKey: "pId",
                    rootPId: ""
                    }
                }
            };
            var zNodes = [
                {id: 1, pId: 0, name: "root", icon:"../static/css/zTreeStyle/img/diy/c16green.png"},
                {id: 2, pId: 1, name: "leaf", icon:"../static/css/zTreeStyle/img/diy/c16red.png"},
                {id: 3, pId: 1, name: "foo", icon: {{ customIcon }} },
            ];
            $(document).ready(function () {
                var t = $("#tree");
                t = $.fn.zTree.init(t, setting, zNodes);
            });
        
            const app = new Vue({
                el: '#app',
                data: {
                    now: new Date(),
                    customIcon : "../static/css/zTreeStyle/img/diy/c16green.png"
                },
                methods: {
                    updateDate() {
                        this.now = new Date();
                    }
                },
                mounted() {
                    setInterval(() => {
                        this.updateDate();
                    }, 1000);
                },
            })
        </script>
    </div>
</BODY>
</HTML>

Zipped sample (examples are inside template directory): https://drive.google.com/file/d/1Ihv8jLdsEz93aUrFjEugD1l6YvslaUT8


Solution

  • The solution contains a few steps:

    1. use "go-echo-vue" for communication between backend and frontend like here: https://github.com/covrom/go-echo-vue

    2. update zTree data using vue-resource and timer like this:

       <script>
       new Vue({
           // ....
           methods: {
               updateZNodes() {
                   // запрашиваем дерево :)
                   this.$http.get('/znodes').then(function (response) {
                       zNodes = response.data.items ? response.data.items : []
                   }, function (error) {
                       console.log(error)
                   });
               },
           },
           mounted() {
               setInterval(() => {
                   this.updateZNodes();
               }, 5000);
           },
           // ....
       })</script>
      
    3. refrest zTree nodes information using js:

       <script language="JavaScript">
               function refreshNode() {
               var treeObj = $.fn.zTree.getZTreeObj("tree");
               var nodes = treeObj.getNodes();
               if (nodes.length > 0) {
                   for (let i = 0; i < nodes.length; i++) {
                       c = "static/css/zTreeStyle/img/diy/c16grey.png";
                       if (zNodes.length >= i) {
                           c = zNodes[i].icon
                       }
                       nodes[i].icon = c;
                       treeObj.updateNode(nodes[i]);
                   }
               }
           };
      
           const timerId = setInterval(
               () => {
                   refreshNode();
               },
               5000
           );
       </script>
      
    4. add async zTree settings:

       <script language="JavaScript">
           var setting = {
               // ....
               async: {
                   enable: true,
                   url: "",
                   autoparam: ["id", "icon"],
                   datatype: "json",
               },
               // ....
           };
       </script>
      

    That's all. So we have Vue function http.get to get fresh data from backend, global js variable to use that data both inside Vue code segment and JavaScript blocks.

    PS additional information: https://www.tutorialfor.com/blog-188266.htm