jerosoler / Drawflow

Simple flow library 🖥️🖱️
https://jerosoler.github.io/Drawflow/
MIT License
4.78k stars 741 forks source link

Proper VUE example or how to bind node props to VUE props? #37

Closed gogzor closed 4 years ago

gogzor commented 4 years ago

Hey!

Just wanted to say that this is a fantastic library, I am building some cool product with it at the moment. But not being a super experienced frontend developer I stuck with Drawflow + Vue integration.

Is it possible to bind node's **df-*** data properties to Vue data properties? Can you provide a complete example or point me to it please?

Thanks.

jerosoler commented 4 years ago

Hello @gogzor

Thanks! 🎉

For vue you have to register the components. View other similar case: https://github.com/jerosoler/Drawflow/issues/34

Example with Vue with props and df properties.

App.vue

<template>
  <div id="app">
    <div id="drawflow"></div>
    <button @click="exportData">Export</button>
  </div>
</template>

<script>
import Vue from 'vue'
/*eslint-disable */
import NodeClick from './components/NodeClick.vue'
import Drawflow from 'drawflow'
import styleDrawflow from 'drawflow/dist/drawflow.min.css' // eslint-disable-line no-use-before-define
/*eslint-enable */

export default {
  name: 'App',
  data() {
    return {
      editor: null,
    }
  },
  mounted() {
    const id = document.getElementById("drawflow");
    this.editor = new Drawflow(id, Vue);
    this.editor.start();
    const props = { name: "Hello gogzor"};
    const options = {};
    this.editor.registerNode('NodeClick', NodeClick, props, options);
    const data = { 'name': '' };
    this.editor.addNode('Name', 0, 1, 150, 300, 'Class', data, 'NodeClick', 'vue');

  },
  methods: {
    exportData() {
      alert(JSON.stringify(this.editor.export()));
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
#drawflow {
  width: 100%;
  height: 500px;
  border: 1px solid red;
}
</style>

Component NodeClick (NodeClick.vue)

<template>
  <div class="card-devices" >
     <div class="header">
        <h1> {{name}} </h1>
     </div>
    <div class="body" >
        <input type="text" df-name>
       <span @click="Clicked"> Name :</span>
     </div>
  </div>
</template>

<script>
export default {
  props: ['name'],
  methods: {
    Clicked() {
      alert("hello-drawflow");
    }
  }
}
</script>

Serves you?

gogzor commented 4 years ago

Yes, thank you!

shahruk10 commented 4 years ago

Hi !

Thank you for sharing such a great plugin ! I am also a beginner with Vue and I tried to use the example exactly as you pasted above, but for some reason the connectors are not starting from the output port. Could you please tell me what I am doing wrong ?
image

jerosoler commented 4 years ago

Hello @shahruk10

Thanks!!!

Remove line the css #app text-align: center;

Or

#drawflow {
  text-align:initial;
  position: relative;
  width: 100%;
  height: 800px;
  border: 1px solid red;
}
shahruk10 commented 4 years ago

Hello @shahruk10

Thanks!!!

Remove line the css #app text-align: center;

Or

#drawflow {
  text-align:initial;
  position: relative;
  width: 100%;
  height: 800px;
  border: 1px solid red;
}

That worked ~ Thank you very much for such a fast reply !

shahruk10 commented 4 years ago

Hi @jerosoler, I had another follow up to the original poster's question:

Is it possible to bind node's df-* data properties to Vue data properties?

if i pass in the node data as :

    const data = { action : 'move' ,  options:  'up'  };
    this.editor.addNode('Name', 0, 1, 150, 300, 'Class', data, 'NodeClick', 'vue');
  1. Can data be accessed other than using the df-* attributes and without using <input> / <textarea> tags ?

  2. Is it possible to store the data in the Vue component data property and use them in the <template> section for dynamically changing the template ? I am mainly using your library to visualize the output of another process (serialized graph), so it would be very useful in that scenario I think. A simple example (I am using vuetify with vue) of :

NodeComponentExample.vue
<template>
    <div>
        <v-icon>  {{ getIcon }} <v-icon>
        <input type="text" df-action>
   </div>
</template>

<script>
export default {
  data() {
     return {
        action: "",    // want to set this to data.action / value of <input> tag
        options: "",  // want to set this to data.options
     };
  },
  computed: {
      getIcon: function () {
        if (this.option == "up") {
            return "mdi-arrow-up-bold";
         }
        if (this.option == "down") {
            return "mdi-arrow-down-bold";
        }
      }, 
  },
}
</script>
jerosoler commented 4 years ago

Hello

You could do something like that with an eventBus, you could also use vuex. Call the parent to pass the data information.

Create event-bus.js

import Vue from 'vue';
const bus = new Vue();
export default bus;

Add in app.vue

import bus from './components/event-bus.js';

And

mounted() {

    const id = document.getElementById("drawflow");
    this.editor = new Drawflow(id, Vue);
    this.editor.start();

    bus.$on('getData', (id) =>  {
      const dataNode = this.editor.getNodeFromId(id.slice(5)).data;
      bus.$emit('SendData', {id, dataNode})
    })

    const props = {};
    const options = {};
    this.editor.registerNode('NodeExample', NodeExample, props, options);

    //const data = {};
    this.editor.addNode('Name', 3, 2, 10, 200, 'Class', { action : 'move' ,  options:  'up'  }, 'NodeExample', 'vue');
    this.editor.addNode('Name', 3, 2, 300, 200, 'Class', { action : 'move2' ,  options:  'down'  }, 'NodeExample', 'vue');

  },

And create a component NodeExample.vue

<template>
  <div>
    <h1>Hello</h1>
    {{ dataId }}
    {{ dataNode }}
  </div>
</template>

<script>
import bus from './event-bus.js';
export default {
  data() {
    return {
      dataId: null,
      dataNode: "tes",
      action: null,
      move: null,
    }
  },
  mounted() {
    this.$nextTick(() => {
      const id = this.$el.parentElement.parentElement.id;
      this.dataId = id;
      bus.$emit('getData',id);
    });

    bus.$on('SendData',  (data) => {
      if(data.id === this.dataId) {
        this.dataNode = data.dataNode;
      }
    });

  },
}
</script>
shahruk10 commented 4 years ago

You could do something like that with an eventBus, you could also use vuex.

Ok got it. Thanks again for the detailed answer ! :D

mofolo commented 3 years ago

Hey @jerosoler

Thank you for your example, how do we go about binding models within the NodeExample component so that the Drawflow export can see the data?

jerosoler commented 3 years ago

Hi @mofolo

With df-* attributes. View https://github.com/jerosoler/Drawflow#nodes

nouseeker commented 1 year ago

Hi @jerosoler How can i add $attrs on Vue component?