Soon you will be able to test my framework for writting node forms using Vue 3 and JSON Schema. This will enable the creation of more complex config forms and write code in an modern way.
Directory structure
.
├── src/
│ └── nodes/
│ └── node-1/
│ ├── schemas/
│ │ ├── config.js
│ │ ├── iput.js
│ │ ├── output-1.js
│ │ ├── output-2.js
│ │ ├── ...
│ │ └── output-n.js
│ ├── client/
│ │ ├── locales/
│ │ │ ├── docs/
│ │ │ │ ├── en-US.md
│ │ │ │ ├── de.md
│ │ │ │ └── ...
│ │ │ └── labels/
│ │ │ ├── en-US.json
│ │ │ ├── de.json
│ │ │ └── ...
│ │ ├── assets/
│ │ │ └── icons/
│ │ │ └── vue.svg
│ │ ├── form.vue
│ │ └── index.js
│ └── server/
│ └── index.js
└── package.json
src/nodes/node-1/client/index.js
import MyComponentForm from "./form.vue";
import MyComponentFormSchema from "../schemas/config.js";
import { defineNode } from "@nrg/core/client";
export default defineNode({
category: "function",
color: "#FFFFFF",
inputs: 1,
outputs: 1,
icon: "vue.png", // TODO: check if I can load base64 asset
form: {
component: MyComponentForm,
schema: MyComponentFormSchema,
},
});
src/nodes/node-1/client/form.vue
<template>
<div>
<div class="form-row">
<label><i class="fa fa-tag"></i> Username</label>
<NodeRedCredentialInput
v-model:value="node.credentials.username"
:error="errors['node.credentials.username']"
/>
</div>
<div class="form-row">
<label><i class="fa fa-tag"></i> Password</label>
<NodeRedCredentialInput
v-model:value="node.credentials.password"
type="password"
:error="errors['node.credentials.password']"
/>
</div>
<div class="form-row">
<label>Typed Input</label>
<NodeRedTypedInput
v-model:value="node.myProperty"
:types="types"
:error="errors['node.myProperty']"
/>
</div>
<div class="form-row">
<label>Typed Input 2</label>
<NodeRedTypedInput
v-model:value="node.myProperty2"
:error="errors['node.myProperty2']"
/>
</div>
<div class="form-row">
<label>Config Input</label>
<NodeRedConfigInput
v-model:value="node.remoteServer"
type="remote-server"
:error="errors['node.remoteServer']"
/>
</div>
<div class="form-row">
<label>Select Input</label>
<NodeRedSelectInput
v-model:value="node.country"
:options="countries"
:error="errors['node.country']"
/>
</div>
<div class="form-row">
<label>MultiSelect Input</label>
<NodeRedSelectInput
v-model:value="node.fruit"
:options="fruits"
multiple
:error="errors['node.fruit']"
/>
</div>
<div class="form-row">
<label>Select Input</label>
<NodeRedSelectInput
v-model:value="node.number"
:options="numbers"
:error="errors['node.number']"
/>
</div>
<div class="form-row">
<label>Select Input</label>
<NodeRedSelectInput
v-model:value="node.object"
:options="objects"
multiple
:error="errors['node.object']"
/>
</div>
<div class="form-row">
<label>Select Input</label>
<NodeRedSelectInput
v-model:value="node.array"
:options="arrays"
:error="errors['node.array']"
/>
</div>
<div class="form-row">
<label>Editor with default height 200px and JSON</label>
<NodeRedEditorInput
v-model:value="node.jsontest"
:error="errors['node.jsontest']"
/>
</div>
<div class="form-row">
<label>Editor with custom height and CSS</label>
<NodeRedEditorInput
v-model:value="node.csstest"
language="css"
style="height: 100px"
:error="errors['node.csstest']"
/>
</div>
</div>
</template>
<script>
export default {
props: {
node: {
type: Object,
required: true,
},
errors: {
type: Object,
default: () => ({}),
},
},
data() {
return {
types: ["str", "msg"],
countries: [
{ value: "usa", label: "usa" },
{ value: "argentina", label: "argentina" },
{ value: "brasil", label: "brasil" },
],
fruits: [
{ value: "apple", label: "apple" },
{ value: "melon", label: "melon" },
{ value: "raspberry", label: "raspberry" },
],
numbers: [
{ value: "1", label: "1" },
{ value: "2", label: "2" },
{ value: "3", label: "3" },
],
objects: [
{ value: JSON.stringify({ test: "a" }), label: "a" },
{ value: JSON.stringify({ test: "b" }), label: "b" },
{ value: JSON.stringify({ test: "c" }), label: "c" },
],
arrays: [
{ value: JSON.stringify(["a"]), label: "a" },
{ value: JSON.stringify(["b"]), label: "b" },
{ value: JSON.stringify(["c"]), label: "c" },
],
};
},
};
</script>
<style scoped>
.label {
width: 100%;
}
</style>