Skip to content

Mubarrat/dom-builder

Repository files navigation

Dom-Builder

Note

Looking for HTML Builder?

You're in the right place — the project has been renamed to Dom-Builder starting from version 3.0.0 for clarity.

If you're using the older html-builder, simply stick to version <3.0.0.


Overview

Dom-Builder is a modern JavaScript library for declaratively constructing and updating DOM elements with simplicity and precision. It improves upon the previous html-builder by offering a cleaner, MVVM-friendly architecture and clearer naming.


What's New in Dom-Builder

You can check out the Wiki for this.


Installation

Download

Download the latest release files from this GitHub repository.

Contents

After extracting the zip, you'll find:

dom-builder
├── dom.d.ts
├── dom.d.ts.map
├── dom.js
├── dom.js.map
├── dom.min.js
└── dom.min.js.map

CDN

<script src="https://cdn.jsdelivr.net/gh/Mubarrat/dom-builder@4.x/dist/dom.js"></script>

Minified:

<script src="https://cdn.jsdelivr.net/gh/Mubarrat/dom-builder@4.x/dist/dom.min.js"></script>

GitHub Package

Not available via GitHub Packages or npm This library is browser-focused and intended to be used directly via <script> tags, not through package managers.

Use the CDN or Releases to include it in your project.


Quick Start

Include the library and write your first elements in under a minute.

<script src="https://cdn.jsdelivr.net/gh/Mubarrat/dom-builder@4.x/dist/dom.js"></script>

Basics

Building Elements

Use the $html builder to create any HTML element declaratively.
The first argument can be an attribute object; all following arguments become children.

// $html.<tagName>( [attributes], ...children )
const card = $html.div({ class: "card", id: "intro" },
  $html.h2("Hello, Dom-Builder!"),
  $html.p("Declarative DOM — no templates needed."),
  $html.a({ href: "https://example.com", target: "_blank" }, "Learn more")
);

document.body.append(card);

Children can be strings, other elements, arrays, or observables.


Attributes & Events

Pass any HTML attribute as a key in the attribute object.

// Inline style — string or object form
const box = $html.div({ style: "color: red; font-weight: bold;" }, "Red text");
const box2 = $html.div({ style: { color: "blue", fontSize: "1.2rem" } }, "Blue text");

// Event listeners — use the `on` prefix or the `on` key for multiple events
const btn = $html.button(
  {
    onclick: () => alert("Clicked!"),
    on: { mouseenter: () => console.log("hover") }
  },
  "Click me"
);

// data-* attributes
const el = $html.div({ data: { userId: 42, role: "admin" } });
// → <div data-user-id="42" data-role="admin">

Reactive State — observable

An observable is a callable getter/setter that notifies the DOM when its value changes.

const count = observable(0);   // create with an initial value

count();        // → 0  (getter: call with no arguments)
count(5);       // → 5  (setter: call with a new value)

// Pass an observable directly as a child — the DOM updates automatically
const display = $html.span(count);

const app = $html.div(
  $html.button({ onclick: () => count(count() - 1) }, "−"),
  display,
  $html.button({ onclick: () => count(count() + 1) }, "+")
);

document.body.append(app);

Observables can also be bound to attributes:

const color = observable("red");
const box = $html.div({ style: { color } }, "Watch me change color");

color("blue");   // box's text color updates immediately

Two-way binding

Passing an observable as the value of an <input> creates a two-way binding:

const name = observable("");
const input = $html.input({ type: "text", value: name });
const greeting = $html.p((() => `Hello, ${name() || "stranger"}!`).computed(name));

document.body.append(input, greeting);

Derived Values — computed & cstr

computed

Turn any zero-argument function into a reactive computed observable by calling .computed() on it and listing the observables it depends on.

const a = observable(3);
const b = observable(4);

const hypotenuse = (() => Math.sqrt(a() ** 2 + b() ** 2)).computed(a, b);

console.log(hypotenuse());   // → 5
a(5); b(12);
console.log(hypotenuse());   // → 13  (updates automatically)

// Use in the DOM just like a plain observable
document.body.append($html.p("Hypotenuse: ", hypotenuse));

cstr — reactive template strings

cstr is a tagged template literal that produces a computed string whenever it contains observable values.

const user  = observable("Alice");
const score = observable(99);

// Automatically re-evaluates when `user` or `score` changes
const label = cstr`${user} scored ${score} points`;

document.body.append($html.p(label));

user("Bob");   // → "Bob scored 99 points"

Reactive Arrays — arrayObservable

arrayObservable wraps a native array with reactive mutations.
Use .bind.map() to render each item into the DOM; the list updates precisely when items are added, removed, or replaced.

const items = arrayObservable(["Apple", "Banana", "Cherry"]);

// .bind.map() returns a read-only mapped observable array
const listEl = $html.ul(
  items.bind.map(item => $html.li(item))
);

document.body.append(listEl);

// Standard array mutations are fully reactive
items.push("Date");           // <li>Date</li> appended
items.splice(1, 1, "Blueberry"); // "Banana" replaced by "Blueberry"
items.reverse();              // entire list re-ordered

Validation — validatable()

Call .validatable(predicateFn) on any observable to attach a reactive isValid computed property.

const email = observable("").validatable(v => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v));

// email.isValid is a computed<boolean> that updates with the value
const input = $html.input({ type: "email", value: email });

const errorMsg = $html.p(
  { style: { color: "red" } },
  (() => email.value && !email.isValid() ? "Invalid email address." : "").computed(email, email.isValid)
);

const submitBtn = $html.button(
  { type: "submit", disabled: (() => !email.isValid()).computed(email.isValid) },
  "Subscribe"
);

document.body.append(input, errorMsg, submitBtn);

More Examples

See the examples/ directory for runnable demos:

Example Highlights
Static Hello World $html basics
Static Static List Mapping arrays
Static Contact Form Events & form
Static Data Table Nested elements
Static SVG Badges $svg namespace
Reactive Live Counter observable
Reactive Todo List arrayObservable, cstr
Reactive Live Search computed
Reactive Registration Form validatable()
Reactive Optimistic Like .optimistic()

Migration from HTML Builder

There are no major breaking changes between html-builder and dom-builder.

Key Points

  • dom-builder is a renamed continuation of html-builder, starting from version 3.0.0.
  • The majority of the API remains declarative and unchanged.
  • The build() method is no longer needed in dom-builder.
  • The long-form new HtmlItem(...) syntax is removed — use concise $html.div(...)-style instead.
  • The new version introduces optional MVVM-style utilities like observable, computed, bind, bindSelect, and bindMap.

See Migration from html-builder for more details.

Tip

Consider adopting MVVM-style view models for better state management.


Documentation

Check out the Wiki for:

  • API Documentation
  • Examples
  • Best Practices
  • Migration from html-builder
  • MVVM Patterns (optional)

License

Dom-Builder is licensed under the MIT License.

About

A lightweight DOM builder library that creates HTML, SVG, and MathML elements using function calls. Supports attributes, event listeners, reactive updates, and nested child elements for declarative UI construction.

Topics

Resources

License

Code of conduct

Stars

Watchers

Forks

Contributors