Components are graphical elements that can render themselves inside a DOM
element. A component is defined by a tiny
interface.
In essense, a component must have a render
method and an unrender
method:
let span = document.createElement('h1');
span.textContent = "Hello, world!";
span.render = e => e.appendChild(span);
span.unrender = () => span.parentElement.removeChild(span);
It can be rendered:
span.render(document.body);
and unrendered:
span.unrender();
While the components system is just a simple interface, without any dependencies, a set of component classes has been used to simplify the creation of components.
Below is a few examples of some of them.
Renders a text.
import { Txt } from 'modapp-base-component';
let txt = new Txt("Hello, world!", { tagName: 'h1' });
txt.render(document.body);
Renders:
<h1>Hello, world!</h1>
See Txt.js for usage.
Renders a DOM structure that may contain subcomponents.
import { Elem, Txt } from 'modapp-base-component';
let elem = new Elem(n => n.elem('ul', { className: 'example' }, [
n.elem('li', [
n.text("First item"),
]),
n.elem('li', [
n.component(new Txt("Second item")),
]),
]));
elem.render(document.body);
Renders:
<ul class="example">
<li>First item</li>
<li>
<span>Second item</span>
</li>
</ul>
See Elem.js for usage.
A component wrapper that creates a context on render, which can be properly disposed on unrender.
import { Context, Txt } from 'modapp-base-component';
let txt = new Context(
// Called prior to render
context => setTimeout(() => context.getComponent()?.setText("Timeout!"), 5000),
// Called after unrender with the value returned above
timeoutId => clearTimeout(timeoutId).removeEventListener('resize', onResize),
// Called on render with the value returned above
timeoutId => new Txt("ID: " + timeoutId),
);
txt.render(document.body);
Renders initially:
<span>ID: 1</span>
After 5 seconds, it changes to:
<span>Timeout!</span>
See Context.js for usage.
Resource components are components that starts listening to events on Models or Collections on render, updating themselves on events, and stops listening on unrender.
Renders a text based on a model, and updates that text on model change.
import { Model } from 'modapp-resource';
import { ModelTxt } from 'modapp-resource-component';
let model = new Model({ data: { place: "world" }});
let txt = new ModelTxt(model, m => "Hello, " + m.place + "!", { tagName: 'h1' });
txt.render(document.body);
setTimeout(() => model.set({ place: "Mucklet" }), 5000);
Renders initially:
<h1>Hello, world!</h1>
After 5 seconds, the model is updated, which updates the text to:
<h1>Hello, Mucklet!</h1>
Renders a list of items based on a collection.
import { Txt } from 'modapp-base-component';
import { Collection } from 'modapp-resource';
import { CollectionList } from 'modapp-resource-component';
let collection = new Collection({ data: [
{ id: 10, greeting: "Hello" },
{ id: 20, greeting: "Hejsan" },
] });
let list = new CollectionList(collection, item => new Txt(item.greeting));
list.render(document.body);
setTimeout(() => collection.add({ id: 30, greeting: "こんにちは" }), 5000);
Renders initially:
<div>
<div><span>Hello</span></div>
<div><span>Hejsan</span></div>
</div>
After 5 seconds, the collection is updated, which animates in a new item:
<div>
<div><span>Hello</span></div>
<div><span>Hejsan</span></div>
<div><span>こんにちは</span></div>
</div>
See CollectionList.js for usage.
A generic component wrapper that listens to change events on a model, calling update on change.
import { Txt } from 'modapp-base-component';
import { Model } from 'modapp-resource';
import { ModelComponent } from 'modapp-resource-component';
let model = new Model({ data: { color: "#F00" }});
let txt = new ModelComponent(
model, // Model to listen to
new Txt("Colored"), // Component to render
(m, c) => c.setStyle('color', m.color), // Callback called before render and on model update
);
txt.render(document.body);
setTimeout(() => model.set({ color: "#0F0" }), 5000);
Renders initially:
<span style="color:#F00">Colored</span>
After 5 seconds, the model is updated, which updates the style to:
<span style="color:#0F0">Colored</span>
See ModelComponent.js for usage.