retejs / vue-plugin

https://retejs.org
MIT License
37 stars 37 forks source link

vue-renderer-plugin not working (with VUE 2.6.10) #12

Closed ulissepress closed 5 years ago

ulissepress commented 5 years ago

HI

i just 'imported' one of the example available in the docs in my vue project| (typescript + VUE CLI 3).

Event is compiling correctly, at runtime I get a series of warning from vue:

[Vue warn]: Property or method "readonly" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.

The result is that visually I see the node (with a textbox inside) but the textbox has no value (emtpy).

Seems that for VUE the component NumberControl.vue does not have the prop 'readyonly' and not have the data 'value' attr.

CODESANDBOX LINK: https://codesandbox.io/s/retejs-test-jw1rz

Here the source code:

NumberControl.vue

<template>
    <input type="number" :readonly="readonly" :style="{ backgroundColor: readonly ? `#555` : `white`, color: readonly ? `white` : `black`}" :value="value" @input="change($event)" @dblclick.stop="" @pointermove.stop="" />
</template>

<script lang="ts">
//@ts-ignore
import Vue, { VueConstructor } from 'vue';

export default Vue.extend(
{    
    props: [ 'readonly', 'emitter', 'ikey', 'getData', 'putData' ],

    data: () =>
    ({ 
        value: 0,
    }),

    methods: 
    {
        change(e: any)
        {
            this.value = +e.target.value;
            this.update();
        },

        update() 
        {
            if (this.ikey) this.putData(this.ikey, this.value)
            this.emitter.trigger('process');
        }
    },

    mounted() 
    {
        this.value = this.getData(this.ikey);
    }

})

Here the rest:

import Vue from 'vue';

import * as Rete from 'rete';
import VueRenderPlugin          from 'rete-vue-render-plugin';
import ConnectionPlugin         from 'rete-connection-plugin'; 
import ContextMenuPlugin        from 'rete-context-menu-plugin';
import AreaPlugin               from 'rete-area-plugin';
import CommentPlugin            from 'rete-comment-plugin';    
import HistoryPlugin            from 'rete-history-plugin';
//import ConnectionMasteryPlugin  from 'rete-connection-mastery-plugin';

import VueNumberControl from './NumberControl.vue';

let numSocket = new Rete.Socket('Number Value');

class NumControl extends Rete.Control 
{
    constructor(emitter, key, readonly = false) 
    {
        super(key);
        this.render    = 'vue';
        this.component = VueNumberControl;
        this.props     = { emitter, ikey: key, readonly };
    }

    setValue(val) 
    {
        this.vueContext.value = val;
    }
}

class NumComponent extends Rete.Component 
{

    constructor()
    {
        super("Number");
    }

    builder(node) 
    {
        var out1 = new Rete.Output('num', "Value", numSocket);

        return node.addControl(new NumControl(this.editor, 'num')).addOutput(out1);
    }

    worker(node, inputs, outputs) 
    {
        outputs['num'] = node.data.num;
    }
}

class MathComponent extends Rete.Component 
{
    doOperation(v1, v2) { return 0;  }

    builder(node) 
    {
        var inp1 = new Rete.Input('num1', "Value 1", numSocket);
        var inp2 = new Rete.Input('num2', "Value 2", numSocket);
        var out  = new Rete.Output('num', "Result",  numSocket);

        inp1.addControl(new NumControl(this.editor, 'num1'))
        inp2.addControl(new NumControl(this.editor, 'num2'))

        return node
            .addInput(inp1)
            .addInput(inp2)
            .addControl(new NumControl(this.editor, 'preview', true))
            .addOutput(out);
    }

    worker(node, inputs, outputs) 
    {
        var n1 = inputs['num1'].length ? inputs['num1'][0] : node.data.num1;
        var n2 = inputs['num2'].length ? inputs['num2'][0] : node.data.num2;
        var sum = this.doOperation(n1, n2);

        this.editor.nodes.find(n => n.id == node.id).controls.get('preview').setValue(sum);
        outputs['num'] = sum;
    }
}

class AddComponent      extends MathComponent { constructor()  { super('Add');      }  doOperation(v1, v2) { return v1 + v2; } }
class SubtractComponent extends MathComponent { constructor()  { super('Subtract'); }  doOperation(v1, v2) { return v1 - v2; } }
class MultiplyComponent extends MathComponent { constructor()  { super('Multiply'); }  doOperation(v1, v2) { return v1 * v2; } }
class DivideComponent   extends MathComponent { constructor()  { super('Divide'); }    doOperation(v1, v2) { return v2 != 0 ? v1 / v2 : 0; } }

export async function createFlowEditor()  
{
    console.log('createFlowEditor()');

    let container = document.querySelector('#my-flow-editor');
    let components = [new NumComponent(), new AddComponent(), new SubtractComponent(), new MultiplyComponent(), new DivideComponent()];

    let editor = new Rete.NodeEditor('demo@0.1.0', container);
    editor.use(ConnectionPlugin);
    editor.use(VueRenderPlugin);
    editor.use(AreaPlugin);
    editor.use(CommentPlugin);
    editor.use(HistoryPlugin);
    //editor.use(ConnectionMasteryPlugin);

    editor.use(ContextMenuPlugin, 
    {
        searchBar: false,                
        items: 
        {
            'Dump JSON': () => { console.log(editor.toJSON()) }
        },
        allocate(component) { return ['+ New']; },
        rename(component)   { return component.name; },      
    });

    let engine = new Rete.Engine('demo@0.1.0');

    components.map(c => 
    {
        editor.register(c);
        engine.register(c);
    });

    let n1  = await components[0].createNode({num: 2});
    //let n2  = await components[0].createNode({num: 0});
    //let add = await components[1].createNode();

    n1.position  = [80, 200];
    //n2.position  = [80, 400];
    //add.position = [500, 240];

    editor.addNode(n1);
    //editor.addNode(n2);
    //editor.addNode(add);

    //editor.connect(n1.outputs.get('num'), add.inputs.get('num1'));
    //editor.connect(n2.outputs.get('num'), add.inputs.get('num2'));

    editor.on('process nodecreated noderemoved connectioncreated connectionremoved', async () => 
    {
        console.log('processing...');
        await engine.abort();
        await engine.process(editor.toJSON());
    });

    // editor.on('nodedraged', async (node) => 
    // {
    //     console.log('node dragged', node);     
    //     let grid = 10; 
    //     node.position[0] = Math.floor(node.position[0] / grid) * grid;
    //     node.position[1] = Math.floor(node.position[1] / grid) * grid;
    // });      

    editor.view.resize();
    AreaPlugin.zoomAt(editor);
    editor.trigger('process');
};

here the packages.json file

{
  "name": "etna-frontend",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build:app": "vue-cli-service build --dest dist/app      src/main.ts",
    "build:dataview": "vue-cli-service build --dest dist/dataview src/etna/views/dataview/build.ts",
    "test:unit": "vue-cli-service test:unit",
    "test:watch": "vue-cli-service test:unit --watch"
  },
  "dependencies": {
    "@babel/polyfill": "^7.4.4",
    "@fortawesome/fontawesome-free": "^5.9.0",
    "date-fns": "^1.30.1",
    "fontfaceobserver": "^2.1.0",
    "fps-indicator": "^1.3.0",
    "leaflet": "^1.5.1",
    "lodash": "^4.17.11",
    "rete": "^1.3.1-rc.3",
    "rete-area-plugin": "^0.2.1",
    "rete-comment-plugin": "^0.5.1",
    "rete-connection-mastery-plugin": "^0.1.0",
    "rete-connection-plugin": "^0.8.0",
    "rete-context-menu-plugin": "^0.4.0",
    "rete-history-plugin": "^0.2.1",
    "rete-vue-render-plugin": "^0.4.0",
    "roboto-fontface": "*",
    "vis": "^4.21.0",
    "vue": "^2.6.10",
    "vue-canvas-gauges": "0.0.0",
    "vue-color": "^2.7.0",
    "vue-dialog-drag": "^0.1.29",
    "vue-graph-vis": "^0.1.4",
    "vue-grid-layout": "^2.3.4",
    "vue-multipane": "^0.9.5",
    "vue-router": "^3.0.6",
    "vue2-leaflet": "^2.1.1",
    "vuetify": "^1.5.14",
    "vuex": "^3.1.1"
  },
  "devDependencies": {
    "@types/chai": "^4.1.0",
    "@types/leaflet": "^1.4.4",
    "@types/lodash": "^4.14.134",
    "@types/mocha": "^5.2.7",
    "@vue/cli-plugin-babel": "^3.8.0",
    "@vue/cli-plugin-typescript": "^3.8.1",
    "@vue/cli-plugin-unit-mocha": "^3.8.0",
    "@vue/cli-service": "^3.8.0",
    "@vue/test-utils": "^1.0.0-beta.29",
    "chai": "^4.1.2",
    "node-sass": "^4.12.0",
    "sass-loader": "^7.0.1",
    "stylus": "^0.54.5",
    "stylus-loader": "^3.0.1",
    "typescript": "^3.5.1",
    "vue-cli-plugin-vuetify": "^0.4.6",
    "vue-template-compiler": "^2.6.10",
    "vuetify-loader": "^1.2.2"
  }
}
ulissepress commented 5 years ago

Question / suggestion: the 'rete-vue-renderer-plugin' should be built having 'vue; as peerDependencies and not as 'dependencies' ?

This way you avoid vue versions conflicts?

Ni55aN commented 5 years ago

Check this component. On rete.js.org its working without warnings

Ni55aN commented 5 years ago

You forgot the </script> at the end of file

ulissepress commented 5 years ago

Hi @Ni55aN thank you for the reply.

I created a CodeSandBox (https://codesandbox.io/s/retejs-test-jw1rz) where you can replicate the issue.

I also replaced my own .vue component with the one suggested by you (link)

Now the initial values in the textbox are displayed (without errors) but when you try to change the values you start getting again JS errors (and of course the rete is not updated / processed):

[Vue warn]: Error in v-on handler: "TypeError: this.change is not a function" TypeError: this.change is not a function ... (+others similar)

PS: BTW my local project is a VUE CLI 3 project :-)

ulissepress commented 5 years ago

Ok I found the issue: I installed latest retejs packages via NPM but the example seems using other version / API. I 'merged' manually my code with this one (https://github.com/retejs/rete.js.org/blob/master/src/rete/controls/field/index.js) and now is working fine.