Dismiss
Announcing Stack Overflow Documentation

We started with Q&A. Technical documentation is next, and we need your help.

Whether you're a beginner or an experienced developer, you can contribute.

Sign up and start helping → Learn more about Documentation →

I'm trying to visualize a tree structure in Vue.js.

A small tree looks like the following:

{
"label": "outlook",
"edges": {
    "== sunny": {
        "label": "== sunny",
        "node": {
            "label": "humidity",
            "edges": {
                "<= 82": {
                    "label": "<= 82",
                    "node": {
                        "label": true
                    }
                },
                "> 82": {
                    "label": "> 82",
                    "node": {
                        "label": false
                    }
                }
            }
        }
    }
}
}

This might not be the most intuitive data structure for a tree, but I ended up with this since I need to display the labels for both the nodes and the edges.

The JSON object is used as input for a Tree component with the following template:

<template id="tree-template">
    <div class="tree clearfix">
        <node v-ref:node :node-data="treeData"></node>
    </div>
</template>

The Node component looks as follows:

<template id="node-template">
    <div class="node">
        <div class="node__children" v-if="hasChildren">
            <div class="node__child" v-for="edge in nodeData.edges">
                <node :node-data="edge.node"></node>
            </div>
        </div>
    </div>
</template>

The problem now is that the child node components do not reflect changes made to the edges property of the JSON object from above. For visualization purposes, the object gets constructed step-by-step using the generator pattern. I.e., I first start off with something like this:

{
"label": "outlook",
"edges": {
    "== sunny": {
        "label": "== sunny",
        "node": {}
    }
}
}

Where the node property of edge == sunny is an empty object. In the next step, that node gets created and is set in the tree data.

I know that changes to object properties are not watched by default, but should still trigger view updates when using Vue.js' $set() method:

this.$set('treeData.edges["== sunny"].node', node);

However, this change is only reflected at the top level (i.e. in the tree component), which I can see by outputting {{ treeData | json }}. Also, in the node component embedded in tree, { nodeData | json }} reflects this change. (I also tried this.$set('treeData', treeData) after having manipulated treeData, but without success).

But if I output {{ edge.node }} in the v-for directive inside the node component, it remains the empty object set during the initialization (and therefore no subsequent nodes are rendered).

I also tried to define an own watcher for this both in the tree and node component, but to no avail:

// ...
watch: {
  'nodeData': {
    handler: function(val, oldVal) {
        console.log('nodeData updated:');
        console.log(val);
    },
      deep: true
  }
}

Any idea how I can get the (recursive) node component to be aware of the changes to treeData / nodeData?

share|improve this question
    
They should be, since all data is sync'd from parent to child by default. This seems like another issue. Maybe since the edges value is an object not an array, you need to use the <div class="node__child" v-for="(key, edge) in nodeData.edges"> syntax? – Jeff Jun 20 at 20:32
    
Unfortunately no improvement using v-for="(key, edge) in nodeData.edges". It seems that the data updates are at least partially working, since I see the changes when outputting {{ nodeData | json }}, it's just that the node property for an edge inside the v-for is not reflecting that change and remains empty. – Kubin Jun 21 at 14:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.