Skip to main content

Integration

You can easily integrate this library with React.js and Vue.js libraries.

React integration​

Nodality ships a React component: import Nodality from "nodality/react" (Nodality 1.3.25 and later, React 18 and later). It hosts a Nodality render inside your React tree, in either of the library's two forms.

To start a new app with it already set up, including build-time prerendering:

npx create-nodality-react@latest my-app

To add it to an existing React app, install nodality and import the component:

npm install nodality

Component code you own: view​

Pass a function that returns a Nodality component, and the values it depends on in deps. The view is rebuilt when deps change, with the same meaning as useEffect's dependency array, and not on every parent render.

import { useState } from "react";
import { Text, Wrapper } from "nodality";
import Nodality from "nodality/react";

export default function Counter() {
const [count, setCount] = useState(0);

return (
<>
<Nodality
view={() =>
new Wrapper().set({ background: "#FFF7ED", pad: [{ a: "1rem" }] }).add([
new Text(`Count ${count}`).set({ size: "S5", color: "#9A3412" }),
])
}
deps={[count]}
/>
<button onClick={() => setCount(count + 1)}>Increment</button>
</>
);
}

A rebuild replaces the view's elements, so a field inside it loses focus when its deps change. Leave values that change on every keystroke out of deps.

A specification: elements and nodes​

Pass the (E, N) pair as data:

import Nodality from "nodality/react";

const elements = [
{ type: "wrap", id: "hero", children: [
{ type: "h1", id: "title", text: "Declared as data" },
]},
];
const nodes = [
{ op: "blast", target: ["title"], color: "#1D6FE0", width: "2px" },
];

export default function Hero() {
return <Nodality elements={elements} nodes={nodes} />;
}

The difference that matters​

Only a specification survives the build. Because it is data, the component writes it into the page next to its host (<script type="application/json" data-nodality-for="…">), and a prerenderer can render it to HTML at build time, so crawlers see real markup. create-nodality-react does this in its npm run build. A view is a function, so it renders in the browser only.

Props​

PropDescription
viewA function returning a Nodality component, e.g. () => new Wrapper()….
depsWhen to rebuild view; same meaning as useEffect's dependency array.
elementsThe specification's elements (E).
nodesThe specification's nodes (N).
defsDefinitions, passed to Des.defs().
className, styleApplied to the host div.

Next.js​

nodality/react is marked "use client", so it works in the Next.js App Router. A server component can render it with elements and nodes, because those are plain data. view is a function, and functions cannot be passed from a server component, so use view inside a client component.

Vue.js integration​

You can also integrate this library with Vue.js. Here is the complete example. To quickly scaffold a Vue app you can use:

npx create-nodality-vue@latest my-app
<template>
<HelloWorld :text="textInstance" v-model:msg="welcomeMessage"/>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import {Text} from "nodality";
export default {
name: 'App',
components: {
HelloWorld
},

watch: {
// Watch for changes to welcomeMessage and recreate the instance
welcomeMessage() {
console.log(this.welcomeMessage) // THIS WORKS
this.textInstance = new Text(this.welcomeMessage).set({ size: "S1", color: "#1abc9c" });
},
},
data() {
return {
welcomeMessage: "Welcome to Your Vue.js App", // Define a reactive property
textInstance: null
}
},

created() {
// Initialize the Text instance when the component is created
this.textInstance = new Text(this.welcomeMessage).set({ size: "S1", color: "#1abc9c" });
},
}
</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;
}
</style>


// 13:21:24 <slot> 26/04/2024

HelloWorld.vue​

<script setup>
import { useTemplateRef, onMounted, defineProps, defineEmits, watch } from 'vue'
//import {Text} from "../lib/TextCopy.js";

// Define props to accept the msg value
const props = defineProps({
msg: String,
text: Object
})

const emit = defineEmits(['update:msg'])

// the first argument must match the ref value in the template
const input = useTemplateRef('my-input')
let mycomp = useTemplateRef('my-comp')

onMounted(() => {
input.value.focus()
let ela = props.text.render();//document.createElement("h1");
mycomp.value.appendChild(ela);
})

watch(() => props.msg, () => { // 12:21:57 Wow!!!

mycomp.value.innerHTML = ""; // Clear existing content
const element = props.text.render(); // Call the render method
mycomp.value.appendChild(element);
})

function updateMessage(event) {
emit('update:msg', event.target.value)
}
</script>

<template>
<input ref="my-input" :value="msg" @input="updateMessage" />
<div ref="my-comp"/>
</template>