In my use case I want to toggle between hierarchical / non-hierarchical views, and to use custom levels for the hierarchy view.
I have looked into the cause and have some observations.
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.
<!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>
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:
I have looked into the cause and have some observations.
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: