Doom is a Virtual Dom Library for Haxe. It is strictly typed (no Dynamics
lurking around) and built to be easy to use.
Examples and demos with source code can be found here.
Make sure to have phantomjs installed.
Run the following commands from the root of the projects:
haxelib install hmm
hmm install
haxe build.hxmlA VNode (virtual node) is the basic rendering element in Doom. It can
represent an element (like a DIV or an A), simple text or a Component.
Generating a VNode doesn't automatically render it. A VNode needs to be
translated into browser DOM nodes. There are two ways to do that:
- mount the
VNodedirectly in the DOM - generate and return a
VNodefrom aComponent.rendermethod.
To mount a VNode use Doom.render.mount():
import doom.html.Html.*;
import js.Browser.document as doc;
class Main {
static function main()
Doom.browser.mount(
h1("I'm just a simple element"),
doc.getElementById("main")
);
}The following VNode types exist:
Element(name: String, attributes: Map<String, AttributeValue>, children: VNodes)Comment(comment: String)Raw(code: String)Text(text: String)Comp<Props, El>(comp: Component<Props, El>)
These can be generated using the homonymous methods on doom.core.VNode, doom.html.Html and/or doom.html.Svg (the last two are convenient aliases). The methods are el, comp, comment, raw and text. doom.html.Html also contains shortcut methods like div or input to generate equivalent
nodes.
Most elements accept child elements, there are typed as VNodes which is an abstract on Array<VNode> with a few additional benefits (mostly implicit cast from common types).
Elements expect a Map<String, AttributeValue> to set the node attributes and properties. AttributeValue is a convenient abstract that simplifies assigning the right values to the attributes.
AttributeValue has 3 constructors:
BoolAttribute(b : Bool)StringAttribute(s : String)EventAttribute<T : Event>(f : T -> Void)
Here are the types that are implicitly converted to AttributeValue:
Stringfor attributes likeidorclassMap<String, Bool>mainly to be used withclass. It is convenient to turn on and off class names:
div([
"class" => [
"button" => true,
"active" => props.active,
style => null != style
]
]);Boolused with attributes likedisabledorcheckedVoid -> Voidan event handler that doesn't care about information related to the even itself.clickis the perfect example for it.(T : Event) -> Voidwhen you want an event handler and have full control on theEventobject.(T : Element) -> Void, the handler receives the original element that triggered the event.String -> Void, the handler receives the text content of the element that triggered the event. The text content is retrieved in different ways according to the type of element (input,textarea,select, ...).Bool -> Void, the handler receives a flag value from thecheckedattribute.Int -> Void, works likeString -> Voidbut tries to convert the value into anInt. If that cannot happen the handler is not invoked.Float -> Void, same asInt -> Voidbut for floats.
Note: All event handlers except for (T : Event) -> Void will automatically
call event.preventDefault().
A component is anything between a full UI application and a button. A component
lives inside another component (as a VNode returned by the render method) or it can be mounted directly in the dom.
import doom.html.Component;
import doom.html.Html.*;
using thx.Objects;
import thx.Timer;
class Main {
static function main() {
var div = js.Browser.document.getElementById("main");
Doom.browser.mount(new BannerComponent({
messages : [ "Doom", "is", "Magic", "(but the good kind)" ],
delay : 500,
toDisplay : 0
}), div);
}
}
class BannerComponent extends Component<BannerProps> {
override function render() {
Timer.delay(function() {
update(props.shallowMerge({
toDisplay : (props.toDisplay + 1) % props.messages.length
}));
}, props.delay);
return h1(props.messages[props.toDisplay]);
}
}
typedef BannerProps = {
messages : Array<String>,
delay : Int,
toDisplay : Int
}- TODO describe update
- TODO describe state