1. Initial Setup
In this example we're using Vite
to develop the project, but you can use whatever developer setup you want.
npm init vite@latest
✔ Project name: … todo-app
✔ Select a framework: › vanilla
✔ Select a variant: › vanilla-ts
2
3
4
5
Then, cd todo-app
, npm install
the packages and run npm run dev
to start your server. Visit http://localhost:3000
to see the Hello Vite
starting point.
To start with muban
, install these two packages;
npm i @muban/muban @muban/template
Our first component
Our first component will be the App
component, which will be the root of our application. To keep things simple, we are only going to render a custom title in the template, with no logic in the component itself.
Template file
Create a src/components/App/App.template.ts
for our template;
import { html, ComponentTemplateResult } from '@muban/template';
export type AppTemplateProps = {
title?: string;
};
export function appTemplate({ title = 'Todos' }: AppTemplateProps): ComponentTemplateResult {
return html`
<div data-component="app">
<h1>${title}</h1>
</div>
`;
}
2
3
4
5
6
7
8
9
10
11
12
13
Here we have done the following;
- We import
html
from@muban/template
, a helper to write our tagged template strings. - We define a
type
for our template props. We always pass our props as an object. Optional props can be marked with a?
in the type, and potentially given a default value when destructuring them. - We create the template itself, which is a normal function, receiving the props as an object, and returning a
ComponentTemplateResult
(which is astring
, or anArray
ofstrings
). Which is what thehtml
helper will return. - We define our root element, adding a
data-component
attribute withapp
, to link it to our TypeScript Component file later. Each template should always have a single root element, that should have a matchingdata-component
attribute. Besides linking it to our logic, it can also be used to style our components (as apposed to classnames). - We use our
title
prop in our html, as you would use any variable in a template string.
Initial State
When rendering any template in Muban, think of it as the initial state of your application or component. Even without executing any component initialisation, your templates should reflect what would be rendered on the server. This means that your templates should not include any "interaction logic". The output should be a static string.
Component file
Now that we have our template, let's create the Component itself by creating src/components/App/App.ts
.
import { defineComponent } from '@muban/muban';
export const App = defineComponent({
name: 'app',
setup() {
console.log('App Running...');
return [];
},
});
2
3
4
5
6
7
8
9
Here we have done the following:
- We import
defineComponent
, which is our factory function to create Muban Components. - As options, we give it a name,
app
in this case. This should match thedata-component
attribute from our template file. - Every component has a
setup
function, where it returnsbindings
. This is the "minimum required" code to be in there, we'll add more things later. - For now, we're adding a
console.log
to check if our component is correctly initialized.
Component Initialisation
A component is only initialized when there is an html element with the matching data-component
attribute value present in the DOM.
Additionally, the Component
file should be registered to a "parent component", or globally to the Muban "application".
In the parent component this can be done by using refComponent
for the refs, or using the components
array. More on this later.
Rendering the App
Now that we have our first component (a template and logic file), it's time to render it by mounting our Application.
In the main.ts
(that was created by Vite), change the code to this:
import './style.css';
import { createApp } from '@muban/muban';
import { App } from './components/app/App';
import { appTemplate } from './components/app/App.template';
const appRoot = document.getElementById('app')!;
const app = createApp(App);
app.mount(appRoot, appTemplate, {
title: 'Todos',
});
2
3
4
5
6
7
8
9
10
11
12
It does the following things:
- Import
createApp
, for creating our Muban Application. - Import our component and template files.
- Query the root element of our application.
- Call
createApp
by passing ourApp
component, which returns theapp
instance. mount
our application in theappRoot
, passing theappTemplate
to render the HTML, passing thetitle
prop to pass to the template.
If we check the browser, we should see a Todos
title, and App Running...
in the devtools console.
Development mode
Calling mount
with a template + data is normally something we only do in development, or abusing muban to create a client-side-rendered App. The strength of muban lies in working with existing HTML that is rendered on the server.
If you already have HTML on the page, you can leave out the template
and data
arguments.