Search code examples
vue.jsevent-handlinggraph-visualization

How to manage the EventHandlers of v-network-graph in Vue.js instance?


this is my first question asked on stackoverflow!

I'm quite new on Vue.js and I am currently trying to display and interact with a node network graph using the v-network-graph component. I am struggling with using the EventHandler, because I didn't really got how to create it and interact with it. Should I initiate it within another instance and import it directly inside this one? Could you please help me understand how to manage the event handler ?

I tried the following code, expecting it to print in the console the node's id I clicked on:

<script lang="ts">
import { reactive, ref } from 'vue';
import * as vNG from 'v-network-graph';
import {
  ForceLayout,
  ForceNodeDatum,
  ForceEdgeDatum,
} from 'v-network-graph/lib/force-layout';

const graph = ref<vNG.Instance>();
export default {
  data() {
    return {
      nodes: { '': { name: '' } },
      edges: { '': { source: '', target: '' } },
      layouts: {
        nodes: {
          node0: {
            x: 0,
            y: 0,
            fixed: true,
          },
        },
      },
      configs: reactive(
        vNG.defineConfigs({
          node: {
            selectable: true,
            label: {
              direction: 'center',
              color: '#eeeeee',
            },
            normal: {
              radius: 48,
            },
          },
          view: {
            autoPanAndZoomOnLoad: 'fit-content',
            minZoomLevel: 1,
            maxZoomLevel: 2,
            layoutHandler: new ForceLayout({
              positionFixedByDrag: false,
              positionFixedByClickWithAltKey: true,
            }),
          },
        }),
      ),
    };
  },
  methods: {
    async getNodes() {
      await fetch('http://127.0.0.1:5000/getNodes')
        .then((response) => response.json())
        .then((data) => { this.nodes = (data); });
    },
    async getEdges() {
      await fetch('http://127.0.0.1:5000/getEdges')
        .then((response) => response.json())
        .then((data) => { this.edges = (data); });
    },
  },
  beforeMount() {
    this.getNodes();
    this.getEdges();
    const eventHandlers: vNG.EventHandlers = {
      'node:click': ({ node }) => {
        window.console.log(this.nodes[node]);
      },
    };
  },
  mounted() {
    this.$refs.graph.fitToContents();
  },
};
</script>

<template>
  <v-network-graph
    :nodes="nodes"
    :edges="edges"
    :configs="configs"
    :layouts="layouts"
    :event-handlers="eventHandlers"
    ref="graph"
    class="visualization"
  />
</template>

<style>
.visualization {
  width: 100%;
  height: 100vh;
  border: 1px solid #000;
}
</style>


Solution

  • I've understood how to make it thanks to this post. Basically the documentation I was learning with is using Script Setup while I'm using the OptionAPI!

    The actual answer:

    The trick here is to not use the vNG.EventHandlers and to set the event handling Object directly in the data component, and the v-bind directive in the graph element.

    The code (please note that I intentionally removed the useless code that was in the previous post to make a clearer answer):

    <script lang="ts">
    import { reactive, ref } from 'vue';
    import * as vNG from 'v-network-graph';
    
    const graph = ref<vNG.Instance>();
    export default {
      data() {
        return {
          nodes: reactive({ '': { name: '' } }),
          edges: { '': { source: '', target: '' } },
          click_event: {
            'node:click': ({ node }) => {
              window.console.log(this.nodes[node]);
            },
          },
        },
      },
    };
    </script>
    
    <template>
      <v-network-graph
        :nodes="nodes"
        :edges="edges"
        :event-handlers="click_event"
        ref="graph"
        class="visualization"
      />
    </template>