Tiny (2 KB) turboboosted JavaScript library for creating user interfaces

Develop web apps with 100 % JavaScript and web standards.

Introduction

API

Source

Slack

Create HTML elements easily

import { el, mount } from 'redom';

// create HTML element
const hello = el('h1', 'Hello world!');

// mount to DOM
mount(document.body, hello);
<body>
  <h1>Hello world!</h1>
</body>

..also oldskool

<!DOCTYPE html>
<html>
  <body>
    <script src="https://redom.js.org/redom.min.js"></script>
    <script>
      var el = redom.el;
      var mount = redom.mount;

      var hello = el('h1', 'Hello world!');

      mount(document.body, hello);
    </script>
  </body>
</html>
        

Add attributes

import { el, mount } from 'redom';

// create HTML element
const logo = el('img#redom-logo.logo', {
  src: 'img/logo.svg'
});

// mount to DOM
mount(document.body, logo);
<body>
  <img id="redom-logo" class="logo" src="img/logo.svg">
</body>

Listen to events

import { el, mount } from 'redom';

// define Login component
class Login {
  constructor () {
    this.el = el('form#login',
      this.email = el('input.email', { type: 'email' }),
      this.pass = el('input.pass', { type: 'password' }),
      this.submit = el('button', { type: 'submit' },
        'Sign in'
      )
    );
    this.el.onsubmit = e => {
      e.preventDefault();

      const email = this.email.value;
      const pass = this.pass.value;

      console.log(email, pass);
    };
  }
}

// create login
const login = new Login();

// mount to DOM
mount(document.body, login);
<body>
  <form id="login">
    <input class="email" type="email">
    <input class="pass" type="password">
    <button type="submit">Sign in</button>
  </form>
</body>

Sync lists

import { el, list, mount } from 'redom';

// define <li> component
class Li {
  constructor () {
    this.el = el('li');
  }
  update (i) {
    this.el.textContent = `Item ${i}`;
  }
}

// create list
const ul = list('ul', Li);

// update with data
ul.update([1, 2, 3]);

// mount to DOM
mount(document.body, ul);

// schedule another update
setTimeout(() => {
  ul.update([2, 3, 4, 5]);
}, 1000);
<body>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</body>

Sync tables

import { el, list, mount } from 'redom';

// define <td> component
class Td {
  constructor () {
    this.el = el('td');
  }
  update (i) {
    this.el.textContent = i;
  }
}

// define <tr> component by extending list
const Tr = list.extend('tr', Td);

// create table
const table = list('table', Tr);

// update with data
table.update([
  [ 1, 2, 3 ],
  [ 4, 5, 6 ],
  [ 7, 8, 9 ]
]);

// mount to DOM
mount(document.body, table);

// schedule another update
setTimeout(() => {
  table.update([2, 3, 4, 5]);
}, 1000);
<body>
  <table>
    <tr>
      <td>1</td><td>2</td><td>3</td>
    </tr>
    <tr>
      <td>4</td><td>5</td><td>6</td>
    </tr>
    <tr>
      <td>7</td><td>8</td><td>9</td>
    </tr>
  </table>
</body>

Create and update components

import { el, text, mount } from 'redom';

// define component
class Hello {
  // ..how to create it
  constructor () {
    this.el = el('h1',
      'Hello ',
      this.target = text('world'),
      '!'
    );
  }
  // ..and how to update it
  update (target) {
    this.target.textContent = target;
  }
}

const hello = new Hello();

hello.update('RE:DOM');

mount(document.body, hello);
<body>
  <h1>Hello RE:DOM!</h1>
</body>

Combine list + component

import { el, text, list, mount } from 'redom';

// define component
class Hello {
  // ..how to create it
  constructor () {
    this.el = el('h1',
      'Hello ',
      this.target = text(''),
      '!'
    );
  }
  // ..and how to update it
  update ({ id, target }) {
    this.target.textContent = target;
  }
}

// create list of Hello's
const hellos = list('section', Hello, 'id');

// init with some data
const data = [{
  id: 1,
  target: 'RE:DOM'
}, {
  id: 2,
  target: 'world'
}];

hellos.update(data);

// mount to DOM
mount(document.body, hellos);

// schedule an update
setTimeout(() => {
  const data = [{
    id: 2,
    target: 'world'
  }, {
    id: 1,
    target: 'RE:DOM'
  }];

  // reuses DOM elements and only reorders in this case!
  hellos.update (data);
}, 1000);
<body>
  <section>
    <h1>Hello RE:DOM!</h1>
    <h1>Hello world!</h1>
  </section>
</body>

Switch sections

const { el, router, mount } = require('redom');

// define A component
class A {
  constructor () {
    this.el = el('.a')
  }
  update ({ val }) {
    this.el.textContent = val;
  }
}

// define B component
class B {
  constructor () {
    this.el = el('.b')
  }
  update ({ val }) {
    this.el.textContent = val;
  }
}

// define main app component
class App {
  constructor () {
    this.el = el('.app',
      this.sections = router('.content', { a: A, b: B })
    );
  }
  update ({ section, data }) {
    this.sections.update(section, data[section]);
  }
}

// create app
const app = new App();

// init app
app.update({
  section: 'a',
  data: {
    a: 1,
    b: 2
  }
});

// mount to DOM
mount(document.body, app);

// update app after 1 second
setTimeout(() => {
  app.update({
    section: 'b',
    data: {
      a: 1,
      b: 2
    }
  });
}, 1000);
<body>
  <div class="app">
    <div class="content">
      <div class="a">1</div>
    </div>
  </div>
</body>

Works on server-side as well!

const { Document, render } = require('nodom');

// create a fake DOM before requiring RE:DOM
const document = new Document();

const { el, mount } = require('redom');

mount(document.body, el('h1', 'Hello world!'));

const html = render(document.body);

console.log(html); // <body><h1>Hello world!</h1></body>

Looks fun!

Learn more on Github!