dash14 / v-network-graph

An interactive network graph visualization component for Vue 3
https://dash14.github.io/v-network-graph/
MIT License
518 stars 44 forks source link

Reload graph not working as expected #160

Open johnfercher opened 1 month ago

johnfercher commented 1 month ago

I'm requesting a graph from a backend and the response currently works. But when I have a form which changes the backend response the graph can´t reload properly.

  1. Vue mount doing request to the backend, and using response to set nodes and edges.
  2. Rendering Works
  3. Change a checkbox which chages the backend request.
  4. Do a new backend request which changes de response.
  5. Use the new set of nodes and edges.
  6. Rendering Keeps the old version.
<style scoped>
.graph {
  border: solid red 1px;
  height: 1080px;
}
</style>

<template>
  <div class="dropdown">
    <button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
      States
    </button>
    <ul class="dropdown-menu">
      <div v-for="[state, active] of statesPicker" class="col">
        <div class="form-check form-switch">
          <input v-if="active" v-on:click="toggleState(state)" class="form-check-input" type="checkbox" id="flexSwitchCheckDefault" checked>
          <input v-if="!active" v-on:click="toggleState(state)" class="form-check-input" type="checkbox" id="flexSwitchCheckDefault">
          <label class="form-check-label"  for="flexSwitchCheckDefault">{{ state }}</label>
        </div>
      </div>
    </ul>
  </div>
  <div v-if="graph !== null">
    <v-network-graph
        class="graph"
        :zoom-level="0.5"
        :nodes="graph.nodes"
        :layouts="graph.layouts"
        :edges="graph.edges"
        :configs="configs"
    >
      <template #edge-label="{ edge, ...slotProps }">
        <v-edge-label
            :text="edge.label"
            align="center"
            vertical-align="above"
            v-bind="slotProps" />
      </template>
    </v-network-graph>
  </div>
  <div v-if="graph === null">
    Loading...
  </div>
</template>

<script>
import axios from "axios";
import VNetworkGraph from "v-network-graph"
import * as vNG from "v-network-graph"
import {reactive} from "vue";

export default {
  name: 'HelloWorld',
  props: {
    VNetworkGraph,
  },
  data() {
    return {
      graph: {
        nodes: [],
        edges: [],
        layouts: {
          nodes: [],
        }
      },
      states: [],
      statesPicker: null,
      configs: reactive(
          vNG.defineConfigs({
            node: {
              normal: {
                radius: n => n.radius,
                color: n => n.color,
                borderRadius: n => n.border_radius,
                type: n => n.type,
                width: n => n.width,
                height: n => n.height,
                x: n => n.x,
                y: n => n.y,
              },
              label: {
                visible: true,
                color: "#ffffff",
                direction: "center",
                fontSize: 11,
                scale: 100,
              },
            },
            edge: {
              selectable: true,
              normal: {
                width: 3,
                color: e => e.color,
                dasharray: "0",
                linecap: "butt",
                animate: false,
                animationSpeed: 50,
              },
              gap: 30,
              type: e => e.type,
              margin: 10,
              marker: {
                source: {
                  type: "none",
                  width: 4,
                  height: 4,
                  margin: -1,
                  offset: 0,
                  units: "strokeWidth",
                  color: null,
                },
                target: {
                  type: "none",
                  width: 4,
                  height: 4,
                  margin: -1,
                  offset: 0,
                  units: "strokeWidth",
                  color: null,
                },
              },
            },
          })
      )
    }
  },
  async mounted() {
    await this.getStates();
    this.mapStates();
    await this.getGraph(this.states);
  },
  methods: {
    async getGraph() {
      var search = {
        "source_label": "City",
        "target_label": "City",
        "source_city_type": "",
        "target_city_type": "",
        "edge_type": "",
        "states": this.states,
      }

      console.log(this.states)

      const graph = await axios.post("http://localhost:8083/graph/search", search).then(response => {
        return response.data
      }).catch(err => {
        return err
      })

      this.graph.nodes = graph.nodes
      this.graph.edges = graph.edges
      this.graph.layouts.nodes = graph.nodes
    },
    async getStates() {
      const data = await axios.get("http://localhost:8083/states").then(response => {
        return response.data
      }).catch(err => {
        return err
      })

      this.statesPicker = new Map();
      data.states.forEach(x => {
        this.statesPicker.set(x, this.randomBool())
      })
    },
    toggleState(state) {
      this.statesPicker.set(state, !this.statesPicker.get(state))
      this.mapStates();
      this.getGraph()
    },
    mapStates() {
      this.states = []
      this.statesPicker.forEach((active, key) => {
        if(active === true) {
          this.states.push(key)
        }
      })
    },
    randomBool() {
      return Math.floor(Math.random() * 100) % 2 === 0
    }
  }
}
</script>
dash14 commented 1 month ago

Hi @johnfercher, Do you mean that updating the data in the getGraph function does not update the network graph display? I checked by running the code you provided, but could not reproduce it on my end. I actually don't have an API, so I changed the process to download a JSON file to check. Other library versions may also be involved, so if you could provide the entire project (including package.json and independent of external APIs or data) that can be reproduced by itself, that would be helpful.