retejs / rete

JavaScript framework for visual programming
https://retejs.org
MIT License
10.16k stars 654 forks source link

Uncaught (in promise) Error: The key parameter is missing in super() of Control #561

Closed MSoup closed 1 year ago

MSoup commented 2 years ago

Hi there, I'm having some difficulties getting set up. This seems like a really cool project, and I'd love to be able to play around with it.

I am encountering this error:

Uncaught (in promise) Error: The key parameter is missing in super() of Control 
    at new Control (webpack-internal:///./node_modules/rete/build/rete.esm.js:534)
    at NumControl._createSuperInternal (webpack-internal:///./node_modules/@babel/runtime/helpers/esm/createSuper.js:26)
    at new NumControl (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader-v16/dist/index.js?!./src/App.vue?vue&type=script&lang=js:84)
    at _callee$ (webpack-internal:///./node_modules/cache-loader/dist/cjs.js?!./node_modules/babel-loader/lib/index.js!./node_modules/cache-loader/dist/cjs.js?!./node_modules/vue-loader-v16/dist/index.js?!./src/App.vue?vue&type=script&lang=js:134)
    at tryCatch (webpack-internal:///./node_modules/regenerator-runtime/runtime.js:63)
    at Generator.invoke [as _invoke] (webpack-internal:///./node_modules/regenerator-runtime/runtime.js:294)
    at Generator.eval [as next] (webpack-internal:///./node_modules/regenerator-runtime/runtime.js:119)
    at asyncGeneratorStep (webpack-internal:///./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:9)
    at _next (webpack-internal:///./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:31)
    at eval (webpack-internal:///./node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js:38)

These are the steps to reproduce my error:

      var in1 = new Rete.Input('num1', 'Number', numSocket);
      var in2 = new Rete.Input('num2', 'Number', numSocket, true); // may have many connections
      var out = new Rete.Output('Number', numSocket); // the third parameter must be false to disable multiple connections

      var numControl = new NumControl();

      var numNode = new Rete.Node('Add');
      numNode.addInput(in1);
      numNode.addInput(in2);
      numNode.addControl(numControl);
      numNode.addOutput(out);

And I realized that I didn't define what NumControl was, so I did more digging through the documentation and came across this:

class NumControl extends Rete.Control {
  constructor(emitter, key, readonly) {
    super(key);
    this.component = VueNumControl;
    this.props = { emitter, ikey: key, readonly };
  }

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

But throwing this on I realized that I need to define VueNumControl, so I did some more digging and found this

const VueNumControl = {
  props: ['readonly', 'emitter', 'ikey', 'getData', 'putData'],
  template: '<input type="number" :readonly="readonly" :value="value" @input="change($event)" @dblclick.stop=""/>',
  data() {
    return {
      value: 0,
    }
  },
  methods: {
    change(e){
      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);
  }
}

So now I think I have all the puzzle pieces to begin making nodes and putting them on the DOM. Forgive me if I'm asking a very basic question. It compiles successfully, but I get the above error which prevents the DOM from displaying any nodes to me.


Here is my full Vue.app

<template>
  <div id="rete" ref="rete" class="node-editor"></div>
  <p>Hi</p>
</template>

<script>
import Rete from "rete";
import ConnectionPlugin from 'rete-connection-plugin';
import VueRenderPlugin from 'rete-vue-render-plugin';
import CommentPlugin from 'rete-comment-plugin';

const numSocket = new Rete.Socket('Number value');

const VueNumControl = {
  props: ['readonly', 'emitter', 'ikey', 'getData', 'putData'],
  template: '<input type="number" :readonly="readonly" :value="value" @input="change($event)" @dblclick.stop=""/>',
  data() {
    return {
      value: 0,
    }
  },
  methods: {
    change(e){
      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);
  }
}

class NumComponent extends Rete.Component {
  constructor() {
    super('Number');
  }

  builder(node) {
    let out = new Rete.Output('num', 'Number', numSocket);

    node.addOutput(out);
  }

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

class NumControl extends Rete.Control {
  constructor(emitter, key, readonly) {
    super(key);
    this.component = VueNumControl;
    this.props = { emitter, ikey: key, readonly };
  }

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

export default {
  name: "App",
  components: {
  },
  methods: {
    async init() {

      let container = this.$refs.rete
      const editor = new Rete.NodeEditor('demo@0.1.0', container);
      editor.use(CommentPlugin, { margin: 20 });
      editor.use(ConnectionPlugin)
      editor.use(VueRenderPlugin)

      const numComponent = new NumComponent();
      editor.register(numComponent);

      const engine = new Rete.Engine('demo@0.1.0');
      engine.register(numComponent);

      var in1 = new Rete.Input('num1', 'Number', numSocket);
      var in2 = new Rete.Input('num2', 'Number', numSocket, true); // may have many connections
      var out = new Rete.Output('Number', numSocket); // the third parameter must be false to disable multiple connections

      var numControl = new NumControl();

      var numNode = new Rete.Node('Add');
      numNode.addInput(in1);
      numNode.addInput(in2);
      numNode.addControl(numControl);
      numNode.addOutput(out);

      // let n1 = await NumComponent.createNode({ num: 2 });
      // let n2 = await NumComponent.createNode({ num: 3 });
      // let add = await NumComponent.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 () => {
      //     await engine.abort();
      //     await engine.process(editor.toJSON());
      // });

    }
  },

  mounted() {
    this.init()
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#rete {
  height: 600px;
  border: solid;
}
</style>

Any advice to set me on the right direction would be hugely appreciated. My apologies if I'm missing any important information.

ArthurHoaro commented 2 years ago
class NumControl extends Rete.Control {
  constructor(emitter, key, readonly) {
    super(key);

and

var numControl = new NumControl();

You forgot your controller parameters, so the key parameter is missing in super() of NumControl.

MSoup commented 2 years ago

Thank you for your response. I'm embarrassed to admit that I don't know what should be passed into "key".

I looked here and did a search for controls (https://rete.js.org/#/docs/controls#lang=en&tosearch=NumControl%20 ), but couldn't find an example.

rete-js[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 10 days.