dataroom.js

Dataroom.js extends the CustomHTML Element API with a few custom features for ease of use.

It's like React, but cooler!

Install dataroom.js from NPM:

npm install dataroom-js
      

1. Extending DataroomElement

Create your own components by extending the base class. Override lifecycle methods like initialize() and disconnect() to add your own logic.

Code Example:


// 1. Import the base class
import DataroomElement from 'dataroom-js';

// you can also use a CDN:
// import DataroomElement from 'https://unpkg.com/dataroom-js@0.7.5/src/index.js';

// 2. Create your own class that extends it
class ExtendingExample extends DataroomElement {
  // 3. Override initialize() for setup logic
  async initialize() {
    this.log('Component is initializing!');
    this.innerHTML = 'Hello from the initialize() method!';
  }

  // 4. Override disconnect() for cleanup logic
  async disconnect() {
    // This won't be visible on the page, but will fire if the element is removed
    console.log('Component is disconnecting!');
  }
}

// 5. Define the new custom element
customElements.define('extending-example', ExtendingExample);
      

Live Demo:

2. this.create()

Dynamically create and append HTML elements within your component.

Code Example:


import DataroomElement from './src/index.js';

class CreateExample extends DataroomElement {
  async initialize() {
    const list = this.create('ul', { style: 'padding-left: 20px;' });
    this.create('li', { content: 'First item' }, list);
    this.create('li', { content: 'Second item' }, list);
  }
}
customElements.define('create-example', CreateExample);
      

Live Demo:

3. this.event(), this.on(), and this.once()

Fire and listen for custom events within your component. once is a variation of on that only fires the event once.

Code Example:


import DataroomElement from './src/index.js';

class EventExample extends DataroomElement {
  async initialize() {
    const onBtn = this.create('button', { content: 'Click Me (on)' });
    onBtn.addEventListener('click', () => {
      this.event('user-clicked', { time: new Date().toLocaleTimeString() });
    });

    this.on('user-clicked', (detail) => {
      alert(`'user-clicked' event caught at ${detail.time}!`);
    });

    const onceBtn = this.create('button', { content: 'Click Me (once)' });
    const status = this.create('p', { content: 'Waiting for one-time event...' });
    onceBtn.addEventListener('click', () => {
      this.event('one-time-event', { time: new Date().toLocaleTimeString() });
    });

    this.once('one-time-event', (detail) => {
      status.textContent = `'one-time-event' caught at ${detail.time}. It won\'t fire again.`;
      onceBtn.disabled = true;
    });
  }
}
customElements.define('event-example', EventExample);
      

Live Demo:

4. this.call()

A built-in helper for making fetch requests. This example fetches a todo item from a public API.

Code Example:


import DataroomElement from './src/index.js';

class CallExample extends DataroomElement {
  async initialize() {
    const btn = this.create('button', { content: 'Fetch Data' });
    const resultEl = this.create('p', { content: 'Waiting for data...' });

    btn.addEventListener('click', async () => {
      resultEl.textContent = 'Loading...';
      try {
        const data = await this.call('https://jsonplaceholder.typicode.com/todos/1');
        resultEl.textContent = `Fetched: "${data.title}"`;
      } catch (e) {
        resultEl.textContent = `Error: ${e.message}`;
      }
    });
  }
}
customElements.define('call-example', CallExample);
      

Live Demo:

5. this.getJSON()

A utility for fetching and parsing a JSON file from a URL. It provides detailed error handling for common issues like network failures or malformed JSON.

Code Example:


import DataroomElement from './src/index.js';

class GetJsonExample extends DataroomElement {
  async initialize() {
    const btn = this.create('button', { content: 'Fetch JSON Data' });
    const resultEl = this.create('p', { content: 'Click the button to fetch.' });

    // Create a dummy JSON file for the demo
    const jsonData = { user: "Jane Doe", role: "Developer" };
    const jsonBlob = new Blob([JSON.stringify(jsonData)], { type: 'application/json' });
    const jsonUrl = URL.createObjectURL(jsonBlob);

    btn.addEventListener('click', async () => {
      resultEl.textContent = 'Loading...';
      try {
        const data = await this.getJSON(jsonUrl);
        resultEl.textContent = `Fetched: User \"${data.user}\" has role \"${data.role}\".`;
      } catch (e) {
        resultEl.textContent = `Error: ${e.message}`;
      }
    });
  }
}
customElements.define('get-json-example', GetJsonExample);
      

Live Demo:

6. Attribute Observation

Components automatically listen for attribute changes and fire a NODE-CHANGED event. Click the button to change the data-id attribute on the component below.

Code Example:


import DataroomElement from './src/index.js';

class AttributeExample extends DataroomElement {
  async initialize() {
    this.on('NODE-CHANGED', (detail) => {
      if (detail.attribute === 'data-id') {
        this.textContent = `Attribute 'data-id' changed to: ${detail.newValue}`;
      }
    });
  }
}
customElements.define('attribute-example', AttributeExample);
      

Live Demo:

I'm waiting for an attribute change...