Views
Some Nodes may need to display UI elements such as text inputs, buttons, or maps. To create a Node with UI elements, follow these three steps:
- Set the
environment
tobrowser
in themanifest.yaml
file - Add a property with a
web-view
datatype (usually namedview
) - Define a render function for the
view
property
name: Visual Node
environments: browser
view:
datatype: web-view
context.set('view', context.render(renderFn));
web-view
is a datatype that indicates the property is a render function that renders a view for the web or browser. In the future, there will be other datatypes for rendering other types of views.
A View Property does not have to use the key view
, other keys can be used. A Node can also have multiple views. However, if your node only has a single view, using view
as the key will follow standard naming convention.
input_view:
datatype: web-view
result_view:
datatype: web-view
Rendering
A render function is a function that produces display elements and adds those elements to the canvas.
For web-view
properties, the render function will produce html elements and given a parentElement, append the elements.
function render(parentElement) {
// Create display element(s)
const button = document.createElement('button');
button.innerHTML = `Count is ${context.get('count')}`;
parentElement.appendChild(button);
}
Setting a View Property
Once a render function and View Property are defined, you can set the render function to the View Property just like any other property.
Setting the render function on a View Property allows it to be displayed either by connecting it to another Node's Viewport Property or used as the Root View.
view:
datatype: web-view
function render(parentElement) {
// Create display element(s)
const button = document.createElement('button');
button.innerHTML = `Count is ${context.get('count')}`;
parentElement.appendChild(button);
}
// Set the render function to the ((view)) property
context.set('view', render);
Render Helper
In order to make defining a render function simpler, Openexus provides a helper function, context.render(), that will append a display element to the parent element.
The render function, when wrapped with context.render(), will only need to return the display elements.
Below is a rewritten example using context.render():
// Note: This render function does not take in a parentElement
function render() {
// Create display element(s)
const button = document.createElement('button');
button.innerHTML = `Count is ${context.get('count')}`;
// Return elements to display
return button;
}
// Set the render function to the ((view)) property, wrapping it with the context.render() helper
context.set('view', context.render(render));
Working with Frameworks
Each framework has its own approach to rendering. These might include creating elements or using JSX/TSX. Openexus has provided context.render() helpers for React, Solid, Svelte, and Vue, allowing for render functions to just be component definitions. Please consult our extensive Framework documentation to learn more details.
Example
- Vanilla
- React
- Vue
- Svelte
- Solid
Simple counter button example without using any external libraries.
name: Counter (JavaScript)
description: An example using JavaScript and no framework to render a simple button that displays the number of times the button is clicked.
categories: starter/javascript,starter/vanilla
keywords: starter,javascript,vanilla,counter
icon: logos:javascript
environments: browser
sandbox: browser.shadow
view:
datatype: web-view
count:
datatype: number
description: The number of times the button has been clicked since this application was started. This represents using a simple Property in the Openexus system.
default: 1
/**
* An example using JavaScript and no framework to render a simple
* button that displays the number of times the button is clicked.
*/
let button;
// Define a render function to return our HTMLElement to display.
function render() {
// Create the element.
button = document.createElement('button');
// Populate the element.
button.innerHTML = `Count is ${context.get('count')}`;
// Openexus components use tailwind by default, but you can define CSS
// classes and styles in your preferred manner.
button.classList.add('bg-blue-500', 'hover:bg-blue-700', 'text-white', 'py-2', 'px-4', 'rounded');
// For our button we want to mutate our count state when it is clicked.
button.addEventListener('click', (value) => {
context.set('count', context.get('count') + 1);
});
return button;
}
// Register to be notified when ((count)) changes.
context.subscribe('count', (value) => {
if (button) button.innerHTML = `Count is ${value}`;
});
// Set our render function to the ((view)) property for rendering.
context.set('view', context.render(render));
Simple counter button example using React.
name: Counter (TypeScript React)
description: An example using TypeScript and the React framework to render a simple button that displays the number of times the button is clicked.
categories: starter/typescript,starter/react
keywords: starter,typescript,react,counter
icon: logos:react
compiler: react@19
environments: browser
sandbox: browser.shadow
view:
datatype: web-view
count:
datatype: number
description: The number of times the button has been clicked since this application was started. This represents using a simple Property in the Openexus system.
default: 1
/**
* An example using TypeScript and the React framework to render a simple
* button that displays the number of times the button is clicked.
*/
// Import needed framework libraries.
import * as reactDom from 'react-dom/client';
import react from 'react';
// Import the openexus setup utility for the React framework.
import { setup } from 'openexus/react';
// Setup openexus to work with React.
setup(context, react, reactDom);
// Define our React component
function ReactComponent(): react.JSX.Element {
// Creates a React state variable that is bound to the ((count)) property.
const [count, setCount] = context.use('count');
// Return our component's JSX.
return (
<button
// For our button we want to mutate our count state when it is clicked.
onClick={() => setCount(count + 1)}
// Openexus components use tailwind by default, but you can define CSS
// classes and styles in your preferred manner.
class='bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded'
>
{`Count is ${count}`}
</button>
);
}
// Set our React component to the ((view)) property for rendering.
context.set('view', context.render(ReactComponent));
Simple counter button example using Vue.
name: Counter (TypeScript Vue)
description: An example using TypeScript and the Vue framework to render a simple button that displays the number of times the button is clicked.
categories: starter/typescript,starter/vue
keywords: starter,typescript,vue,counter
icon: logos:vue
compiler: vue@3
environments: browser
sandbox: browser.shadow
view:
datatype: web-view
count:
datatype: number
description: The number of times the button has been clicked since this application was started. This represents using a simple Property in the Openexus system.
default: 1
<script setup>
// Define our Vue component
// Creates a Vue state variable that is bound to the ((count)) property.
const countRef = context.use('count');
// For our button we want to mutate our count state when it is clicked.
function onClick() {
countRef.value = countRef.value + 1;
}
</script>
<!--
Openexus components use tailwind by default, but you can define CSS
classes and styles in your preferred manner.
-->
<!-- Return our component's JSX. -->
<template>
<button @click="onClick" class="bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded">
Count is {{ countRef }}
</button>
</template>
/**
* An example using TypeScript and the Vue framework to render a simple
* button that displays the number of times the button is clicked.
*/
// Import needed framework libraries.
import * as vue from 'vue';
// Import the openexus setup utility for the Vue framework.
import { setup } from 'openexus/vue';
// Import our child vue component.
import VueComponent from './VueComponent.vue';
// Setup openexus to work with Vue.
setup(context, vue);
// Set our Vue component to the ((view)) property for rendering.
context.set('view', context.render(VueComponent));
Simple counter button example using Svelte.
name: Counter (TypeScript Svelte)
description: An example using TypeScript and the Svelte framework to render a simple button that displays the number of times the button is clicked.
categories: starter/typescript,starter/svelte
keywords: starter,typescript,svelte,counter
icon: devicon:svelte
compiler: svelte@5
environments: browser
sandbox: browser.shadow
view:
datatype: web-view
count:
datatype: number
description: The number of times the button has been clicked since this application was started. This represents using a simple Property in the Openexus system.
default: 1
/**
* An example using TypeScript and the Svelte framework to render a simple
* button that displays the number of times the button is clicked.
*/
// Import needed framework libraries.
import * as svelteStore from 'svelte/store';
import * as svelte from 'svelte';
// Import the openexus setup utility for the Svelte framework.
import { setup } from 'openexus/svelte';
// Import our child Svelte component.
import SvelteComponent from './SvelteComponent.svelte';
// Setup openexus to work with Svelte.
setup(context, svelte, svelteStore);
// Set our component to the ((view)) property for rendering.
context.set('view', context.render(SvelteComponent));
<script lang="ts">
// Define our Svelte component
// Creates a Svelte writable that is bound to the ((count)) property
const countWritable = context.use('count');
let count: number | undefined;
// Register to be notified when ((count)) changes.
countWritable.subscribe((value: number) => {
count = value;
});
// For our button we want to mutate our count writable when it is clicked.
function onClick(): void {
countWritable.set(count + 1);
}
</script>
<!--
Openexus components use tailwind by default, but you can define CSS
classes and styles in your preferred manner.
-->
<!-- Return our component's JSX. -->
<button
on:click={onClick}
class='bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded'
>
Count is {count}
</button>
Simple counter button example using Solid.
name: Counter (TypeScript Solid)
description: An example using TypeScript and the Solid framework to render a simple button that displays the number of times the button is clicked.
categories: starter/typescript,starter/solid
keywords: starter,typescript,solid,counter
icon: logos:solidjs-icon
compiler: solidjs@2
environments: browser
sandbox: browser.shadow
view:
datatype: web-view
count:
datatype: number
description: The number of times the button has been clicked since this application was started. This represents using a simple Property in the Openexus system.
default: 1
/**
* An example using TypeScript and the Solid framework to render a simple
* button that displays the number of times the button is clicked.
*/
// Import needed framework libraries.import * as solidWeb from 'solid-js/web';
import * as solidWeb from 'solid-js/web';
import * as solid from 'solid-js';
// Import the openexus setup utility for the Solid framework.
import { setup } from 'openexus/solid';
// Setup openexus to work with Solid.
setup(context, solid, solidWeb);
// Define our Solid component
function SolidComponent() {
// Creates a Solid signal that is bound to the ((count)) property.
const [count, setCount] = context.use('count');
return (
<button
// For our button we want to mutate our count signal when it is clicked.
onClick={() => setCount(count() + 1)}
// Openexus components use tailwind by default, but you can define CSS
// classes and styles in your preferred manner.
class='bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded'
>{`Count is ${count()}`}</button>
);
}
// Set our Solid component to the ((view)) property for rendering.
context.set('view', context.render(SolidComponent));