Getting started with Drayman
Drayman is a server-side component framework that allows you to use any available HTML element, web component or custom Drayman third-party component together with server-side code in a single script.
With Drayman, the browser only renders what the user should see - all logic and calculations happen server-side and UI is written using JSX syntax.
The best way to show Drayman capabilities is to create something with it. So let's get started.
#
File viewer componentLet's build a component that allows the user to select a file from the file system and view it's contents.
First, you need to install Drayman. It can be done by running these commands:
npx @drayman/framework-init@latest my-appcd my-appnpm start
The website will be available at http://localhost:3033.
#
Initial component templateGo to src/components/home.tsx
and replace its contents with this code:
export const component: DraymanComponent = async () => { return async () => { return ( <> <p>Select a file to view it directly from file system</p> <select></select> <br /> <pre></pre> </> ); };};
You will see an initial skeleton of our component. Further <select>
will be used to show available files and <pre>
will show contents of the selected file.
#
Filling select with optionsBecause Drayman runs a component server-side, we can use any Node.js library. In our case we will use the fs
module.
Let's read file names from the project root directory and fill <select>
options with them:
import { promises as fs } from "fs";
export const component: DraymanComponent = async () => { const files = (await fs.readdir("./")).filter((x) => x.includes("."));
return async () => { return ( <> <p>Select a file to view it directly from file system</p> <select> {files.map((fileName) => ( <option>{fileName}</option> ))} </select> <br /> <pre></pre> </> ); };};
Right now our component is only showing some elements without any interactivity. Our next step will be to add it.
#
Reacting to user actionsWe need to remember which file the user has selected to show its contents. It can be done by using the onchange
event attribute and attaching a function that will be executed server-side. We also need to add the value
attribute to each option
so that select
would know which option was selected.
Let's also add the fs.readFile
function inside the <pre>
tag so that Drayman would read file contents during re-render. We won't show the pre
until a file is actually selected:
import { promises as fs } from "fs";
export const component: DraymanComponent = async () => { const files = (await fs.readdir("./")).filter((x) => x.includes(".")); let selectedFile;
return async () => { return ( <> <p>Select a file to view it directly from file system</p> <select onchange={async ({ value }) => { selectedFile = value; }} > {files.map((fileName) => ( <option value={fileName}>{fileName}</option> ))} </select> <br /> {selectedFile && <pre>{await fs.readFile(selectedFile, "utf-8")}</pre>} </> ); };};
If you make a selection from the dropdown, you will see that nothing happens on the page - file contents don't appear. That is because with Drayman you must strictly tell when a component needs to be re-rendered. It can be done by using a special helper function forceUpdate
.
Import it and add to the onchange
event after the selected file was saved:
import { promises as fs } from "fs";
export const component: DraymanComponent = async ({ forceUpdate,}) => { const files = (await fs.readdir("./")).filter((x) => x.includes(".")); let selectedFile;
return async () => { return ( <> <p>Select a file to view it directly from file system</p> <select onchange={async ({ value }) => { selectedFile = value; await forceUpdate(); }} > {files.map((fileName) => ( <option value={fileName}>{fileName}</option> ))} </select> <br /> {selectedFile && <pre>{await fs.readFile(selectedFile, "utf-8")}</pre>} </> ); };};
Now our component is complete and file contents are shown on select:
#
ConclusionWe have built a component that combines server-side logic and client-side view in a single script.
If this felt interesting to you, visit the official docs to deep-dive into Drayman framework!