Skip to content

Toggling hierarchical mode fails when custom levels are set #2295

@mobley-m

Description

@mobley-m

In my use case I want to toggle between hierarchical / non-hierarchical views, and to use custom levels for the hierarchy view.

Toggling via setOptions:

  • works fine when nodes have no levels set
  • fails if all nodes have levels set, reporting To use the hierarchical layout, nodes require either no predefined levels or levels have to be defined for all nodes.

I have looked into the cause and have some observations.

  • The check to see if level values are set for either all or none of the nodes is working through a list from this.body.nodes
  • If a hierarchical network is created initially, .body.nodes contains only the nodes. This works fine.
  • If a graph is created as - or has become - non-hierarchical then .body.nodes includes edges as well as nodes.
  • Setting such a network to hierarchical fails because the test is now looking at edges (which have no level) as well as nodes (which do).

If there's good reason to hold edges and nodes in .body.nodes when processing a non-hierarchical network then the test needs to use an alternative source containing nodes only for the test.

Here's some code that demonstrates the unexpected behaviour:

<!DOCTYPE html>
<html>
<head>
    <title>Hierarchical Layout Error Demo</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vis-network/9.1.2/dist/vis-network.min.js"></script>
    <style>
        #network { width: 600px; height: 400px; border: 1px solid #ddd; }
        .controls { margin: 10px 0; }
    </style>
</head>
<body>
    <h2>Hierarchical Layout Error Demo</h2>
    <div id="network1"></div>
    <div id="network2"></div>
    <div id="network3"></div>

    <script>
        // Minimal dataset: 2 nodes with custom levels, 1 edge
        const nodes = new vis.DataSet([
            { id: 1, label: 'Node 1', level: 0 },
            { id: 2, label: 'Node 2', level: 1 }
        ]);

        const edges = new vis.DataSet([
            { id: 'Edge1-2', from: 1, to: 2}
        ]);

        const container1 = document.getElementById('network1');
        const container2 = document.getElementById('network2');
        const container3 = document.getElementById('network3');
        const data = { nodes: nodes, edges: edges };
        
        const options_default = {};
        const options_hier_false = {layout: {hierarchical: {enabled: false}}};
        const options_hier_true = {layout: {hierarchical: {enabled: true}}};

        network1 = new vis.Network(container1, data, options_default);
        logNetworkState(network1, 'default options');
        
        network2 = new vis.Network(container2, data, options_hier_false);
        logNetworkState(network2, 'hierarchical false');
        
        network3 = new vis.Network(container3, data, options_hier_true);
        logNetworkState(network3, 'hierarchical true');
        
        // Use setOptions to change to hierarchical layout, catching errors
        try {
            network1.setOptions(options_hier_true);
        } catch (error) {
            console.error('ERROR setting hierarchical true on network1:', error);
        }
        logNetworkState(network1, 'set hierarchical true on network1');

        
        try {
            network2.setOptions(options_hier_true);
        } catch (error) {
            console.error('ERROR setting hierarchical true on network2:', error);
        }
        logNetworkState(network2, 'set hierarchical true on network2');

        try {
            network3.setOptions(options_hier_true);
        } catch (error) {
            console.error('ERROR setting hierarchical true on network3:', error);
        }
        logNetworkState(network3, 'set hierarchical true on network3');

        function logNetworkState(network, options) {
            console.log(`Created with ${options}:`);
            console.log('Nodes:', nodes.get());
            console.log('Edges:', edges.get());
            console.log('body.network.nodes:', network.body.nodes);
        }

    </script>
</body>
</html>

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions