DataTable

A configurable data table for datasets, datasources, filtering, sorting, pagination and row selection workflows.

Import
the javascript logo
import { DataTable } from "@schukai/monster/source/components/datatable/datatable.mjs";
Source
the git logo
Package
the npm logo
Since
1.0.0

Introduction

The Monster Datatable is the main data grid component for dataset views with filtering, sorting, pagination and row actions. Use it when users need to inspect, compare and work with structured records instead of reading a simple static table.

When to use Datatable

  • Use it for operational data views: Lists of orders, users, products or logs benefit from the built-in grid behavior and row actions.
  • Use it when data comes from a datasource: The component integrates well with DOM, REST and other Monster datasource patterns.
  • Use it when users need control over the result set: Pagination, filtering, sorting and row selection are first-class workflows.
  • Do not use it for short static comparisons: If the content is editorial and not interactive, a plain HTML table is often easier and faster.

Key Features

  • Datasource integration: Fill the grid from inline data or from a dedicated datasource without rewriting the table template.
  • Operational controls: Combine filtering, ordering, pagination and selection to support day-to-day backoffice workflows.
  • Template-driven rows: Define columns and row content with Monster templates instead of custom rendering code.
  • Row events and state changes: Listen to documented selection and row mutation events for follow-up UI logic.

Typical mistakes

Start with a clear row template and a stable data contract. Many Datatable problems come from mixing presentation, filtering and datasource concerns too early. If the user only needs a handful of read-only values, a simpler table or metric component usually communicates the information better.

The Empty State

This is a simple and empty datatable. It is a powerful and flexible tool for displaying data in a tabular format. The Monster Datatable is designed to be straightforward to use and highly customizable, making it suitable for a wide range of applications.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";

HTML

<monster-datatable>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

The Data Using Javascript

In this example, the data is set using JavaScript. To do this, the data option is set. The columns are defined in the html using the template.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.querySelector("monster-datatable");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.getElementById("id1agf2");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});</script>

HTML

<monster-datatable>
    <template id="row">
        <div data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

The Alignment

In this example, the data is set using JavaScript. The class `end` is used to align the content to the right, center to the center, and start to the left. So that the content is aligned correctly.

The data-monster-align attribute is used to align the header of the column. The values end, center, and start are used to align the header to the right, center, and left, respectively.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.querySelector("monster-datatable");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.getElementById("id12x23");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});</script>

HTML

<monster-datatable>
    <template id="row">
        <div class="end" data-monster-align="end" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div class="center" data-monster-align="center" data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div class="start" data-monster-align="start" data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div class="center" data-monster-align="center" data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

The Row Mode

The data-monster-row-mode attribute allows you to set the row mode. The default value is visible. Possible values are: visible, hidden, and fixed. Using visible displays the row normally. With hidden, the row is hidden, but the data remains in the DOM, so it can be made visible again through settings or via JavaScript. The fixed option is a special setting that not only makes the row visible but also fixes it in place. It cannot be hidden and remains visible at all times.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.querySelector("monster-datatable");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.getElementById("idRaXe21a");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});</script>

HTML

<monster-datatable>
    <template id="row">
        <div data-monster-mode="fixed" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-mode="hidden" data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-mode="visible" data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div data-monster-mode="hidden" data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-mode="hidden" data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

The Grid Template

The data-monster-grid-template attribute allows you to define the width of individual columns. As shown in the example, a column can be made wider or narrower.

Any valid CSS values can be used for the data-monster-grid-template attribute. For more information, please refer to the CSS specification.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.querySelector("monster-datatable");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.getElementById("idac2df");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "Main Street 1",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "Second Avenue 2",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "Example Road 3",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654",
            "email": "max.mustermann@example.com"
        }
    ]);
});</script>

HTML

<monster-datatable>
    <template id="row">
        <div data-monster-grid-template="1.2rem" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-grid-template="auto" data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-grid-template="3fr" data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

The Overview Class

In this example, we explain the different CSS classes that can be applied to table columns within shadow roots. Since these columns are within the shadow DOM, they can only use internally defined classes. The following classes provide various text and layout handling options.

  • monospace Defines a monospace font, ideal for displaying numbers or IDs that need to be easily compared across rows.

  • ellipsis This class is designed to prevent long text from disrupting the layout. When applied, the text is truncated with an ellipsis if it overflows the cell width, keeping the table row height fixed and preventing the table from becoming too tall.

  • wrap Enables word wrapping within the cell. When the text reaches the cell boundary, it wraps to the next line, integrating neatly into the layout without overflow.

  • auto Unlike ellipsis, this class prevents text from being truncated. Instead, it adds a horizontal scroll bar for text that exceeds the cell width, allowing users to scroll to view the full content.

  • visible Typically used with components like monster-button-bar that may include pop-ups. Applying this class ensures that the pop-up remains visible when it appears.

  • center, end, start These alignment classes were discussed in a previous example but are included here for completeness. They control the horizontal alignment of content within the cell: center aligns content in the center, end aligns it to the right, and start aligns it to the left.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.querySelector("monster-datatable");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "In Remembrance of the Historic Stories and Heroes of Our City Along the Old Oak Pathway",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456 233353435242 233242 345345345 233242 345345435 233242 233242",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "In Remembrance of the Historic Stories and Heroes of Our City Along the Old Oak Pathway",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321 233242 34534534 534534 233242 234234 233242 233242",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "In Remembrance of the Historic Stories and Heroes of Our City Along the Old Oak Pathway",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654 233242 234234 233242 234234 233242 233242",
            "email": "max.mustermann@example.com"
        }
    ]);
});<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import {domReady} from "@schukai/monster/source/dom/ready.mjs";

domReady.then(() => {
    const datatable = document.getElementById("idFe22aD");
    datatable.setOption('data', [
        {
            "id": 1,
            "name": "John Doe",
            "street": "In Remembrance of the Historic Stories and Heroes of Our City Along the Old Oak Pathway",
            "city": "Berlin",
            "zipcode": "10115",
            "country": "Germany",
            "phone": "+49 30 123456 233353435242 233242 345345345 233242 345345435 233242 233242",
            "email": "john.doe@example.com"
        },
        {
            "id": 2,
            "name": "Jane Doe",
            "street": "In Remembrance of the Historic Stories and Heroes of Our City Along the Old Oak Pathway",
            "city": "Munich",
            "zipcode": "80331",
            "country": "Germany",
            "phone": "+49 89 654321 233242 34534534 534534 233242 234234 233242 233242",
            "email": "jane.doe@example.com"
        },
        {
            "id": 3,
            "name": "Max Mustermann",
            "street": "In Remembrance of the Historic Stories and Heroes of Our City Along the Old Oak Pathway",
            "city": "Hamburg",
            "zipcode": "20095",
            "country": "Germany",
            "phone": "+49 40 987654 233242 234234 233242 234234 233242 233242",
            "email": "max.mustermann@example.com"
        }
    ]);
});</script>

HTML

<monster-datatable>
    <template id="row">
        <div class="monospace" data-monster-mode="fixed" data-monster-head="id"
             data-monster-replace="path:row.id"></div>
        <div class="ellipsis" data-monster-mode="hidden" data-monster-head="name"
             data-monster-replace="path:row.name"></div>
        <div class="auto" data-monster-mode="visible" data-monster-head="street"
             data-monster-replace="path:row.street"></div>
        <div class="auto" data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div class="auto" data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div class="auto" data-monster-mode="hidden" data-monster-head="country"
             data-monster-replace="path:row.country"></div>
        <div class="center wrap monospace" data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div class="ellipsis" data-monster-mode="hidden" data-monster-head="email"
             data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Use A Datasource

In this example, we introduce the concept of a DataSource in Monster. A DataSource is an object that can hold a data structure, making it versatile for managing data within components. Here, we demonstrate a basic example using a DOM-based DataSource.

In this simple setup, data is embedded as JSON within the DOM, specifically in a <script> tag. In real-world scenarios, however, data typically originates from an API through a REST interface. This means that switching the DataSource from a DOM-based source to an API-based source is straightforward and requires minimal adjustments to the setup—without any changes to the structure of the table itself.

To link a DataSource to a DataTable in Monster, use the data-monster-datasource-selector attribute. This attribute points to the id of the element containing the JSON data within the DOM.

In this example, the data-monster-datasource-selector attribute on the DataTable points to #myDataSourceID, which contains the JSON data embedded in the DOM.

By changing the DataSource to point to a REST API instead of a JSON script tag, the DataTable will be populated with data from the external source, while the internal structure and bindings remain unaffected. This makes Monster a flexible tool for integrating data dynamically, suitable for a range of applications from simple to complex.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";</script>

HTML

<monster-datasource-dom id="myDataSourceID">
    <script type="application/json">
        {
            "dataset": [
                {
                    "id": 1,
                    "name": "John Doe",
                    "street": "Main Street 1",
                    "city": "Berlin",
                    "zipcode": "10115",
                    "country": "Germany",
                    "phone": "+49 30 1234.56",
                    "email": "john.doe@example.com"
                },
                {
                    "id": 2,
                    "name": "Jane Doe",
                    "street": "Second Avenue 2",
                    "city": "Munich",
                    "zipcode": "80331",
                    "country": "Germany",
                    "phone": "+49 89 6543.21",
                    "email": "jane.doe@example.com"
                },
                {
                    "id": 3,
                    "name": "Max Mustermann",
                    "street": "Example Road 3",
                    "city": "Hamburg",
                    "zipcode": "20095",
                    "country": "Germany",
                    "phone": "+49 40 1111.11",
                    "email": "max.mustermann@example.com"
                },
                {
                    "id": 4,
                    "name": "Lena Schmidt",
                    "street": "Hauptstrasse 4",
                    "city": "Cologne",
                    "zipcode": "50667",
                    "country": "Germany",
                    "phone": "+49 221 9876.54",
                    "email": "lena.schmidt@example.com"
                },
                {
                    "id": 5,
                    "name": "Markus Meier",
                    "street": "Ringstrasse 5",
                    "city": "Frankfurt",
                    "zipcode": "60311",
                    "country": "Germany",
                    "phone": "+49 69 4321.98",
                    "email": "markus.meier@example.com"
                }
            ]
        }
    </script>
</monster-datasource-dom>


<monster-datatable data-monster-datasource-selector="#myDataSourceID">
    <template id="row">
        <div data-monster-grid-template="1.2rem" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-grid-template="auto" data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-grid-template="3fr" data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Use Pagination

In this example, we introduce pagination to a DataTable in Monster. Like the DataTable, the pagination component also needs to connect to the same DataSource to ensure synchronized data management across both components.

To link both the DataTable and pagination to the DataSource, use the data-monster-datasource-selector attribute. This attribute should be specified on both the DataTable and pagination elements, pointing to the same DataSource id.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";</script>

HTML

<monster-datasource-dom id="myDataSourceID">
    <script type="application/json">
        {
            "dataset": [
                {
                    "id": 1,
                    "name": "John Doe",
                    "street": "Main Street 1",
                    "city": "Berlin",
                    "zipcode": "10115",
                    "country": "Germany",
                    "phone": "+49 30 1234.56",
                    "email": "john.doe@example.com"
                },
                {
                    "id": 2,
                    "name": "Jane Doe",
                    "street": "Second Avenue 2",
                    "city": "Munich",
                    "zipcode": "80331",
                    "country": "Germany",
                    "phone": "+49 89 6543.21",
                    "email": "jane.doe@example.com"
                },
                {
                    "id": 3,
                    "name": "Max Mustermann",
                    "street": "Example Road 3",
                    "city": "Hamburg",
                    "zipcode": "20095",
                    "country": "Germany",
                    "phone": "+49 40 1111.11",
                    "email": "max.mustermann@example.com"
                }
            ],
            "sys": {
                "pagination": {
                    "pages": 10,
                    "objectsPerPage": 3,
                    "currentPage": 2
                }
            }
        }
    </script>
</monster-datasource-dom>


<monster-datatable data-monster-datasource-selector="#myDataSourceID">

    <div slot="bar" class="monster-button-group">
        <monster-embedded-pagination id="pagination" data-monster-datasource-selector="#myDataSourceID"></monster-embedded-pagination>
    </div>

    <template id="row">
        <div data-monster-grid-template="1.2rem" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-grid-template="auto" data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-grid-template="3fr" data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Filer The Data

In this example, we enhance the DataTable in Monster by adding a filter. A filter allows users to search for specific values within the data source, refining the displayed data based on the criteria entered.

To enable filtering in the DataTable, the filter component, DataTable, and pagination must all be connected to the same DataSource. This is achieved by specifying the data-monster-datasource-selector attribute on each component, ensuring they work seamlessly together.

This setup ensures that the filter, table, and pagination components remain in sync. When a user enters text into the filter field, the displayed data in the DataTable and the pagination are both updated to match the filtered results. This configuration makes it easy to manage and display refined data dynamically within Monster.

Filter

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/datatable/filter/range.mjs";
import "@schukai/monster/source/components/datatable/filter/select.mjs";
import "@schukai/monster/source/components/datatable/filter/date-range.mjs";
import "@schukai/monster/source/components/datatable/filter/range.mjs";
import "@schukai/monster/source/components/datatable/filter/input.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";
import "@schukai/monster/source/components/layout/tabs.mjs";<script type="module">import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/datatable/filter/range.mjs";
import "@schukai/monster/source/components/datatable/filter/select.mjs";
import "@schukai/monster/source/components/datatable/filter/date-range.mjs";
import "@schukai/monster/source/components/datatable/filter/range.mjs";
import "@schukai/monster/source/components/datatable/filter/input.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";
import "@schukai/monster/source/components/layout/tabs.mjs";</script>

HTML

<monster-datasource-dom id="myDataSourceID">
    <script type="application/json">
        {
            "dataset": [
                {
                    "id": 1,
                    "name": "John Doe",
                    "street": "Main Street 1",
                    "city": "Berlin",
                    "zipcode": "10115",
                    "country": "Germany",
                    "phone": "+49 30 1234.56",
                    "email": "john.doe@example.com"
                },
                {
                    "id": 2,
                    "name": "Jane Doe",
                    "street": "Second Avenue 2",
                    "city": "Munich",
                    "zipcode": "80331",
                    "country": "Germany",
                    "phone": "+49 89 6543.21",
                    "email": "jane.doe@example.com"
                },
                {
                    "id": 3,
                    "name": "Max Mustermann",
                    "street": "Example Road 3",
                    "city": "Hamburg",
                    "zipcode": "20095",
                    "country": "Germany",
                    "phone": "+49 40 1111.11",
                    "email": "max.mustermann@example.com"
                }
            ]
        }
    </script>
</monster-datasource-dom>


<monster-host>
    <monster-config-manager></monster-config-manager>
</monster-host>

<monster-datatable data-monster-datasource-selector="#myDataSourceID">

    <monster-collapse id="filter-collapse" data-monster-role="filter-collapse">
        <div class="flex">

            <monster-tabs style="width: 100%"
                          data-monster-option-features-opendelay="500"
                          data-monster-option-classes-navigation="monster-theme-background-inherit"
                          data-monster-option-classes-button="monster-theme-background-inherit" id="filtertabs">
                <div data-monster-button-label="Filter" data-monster-state="active" class="active">

                    <monster-datatable-filter id="listfilter1" slot="filter"
                                              data-monster-option-storedconfig-selector="#filtertabs">

                        <label data-monster-label="ID" id="id"
                               data-monster-template="${value | call:range:oid}">
                            ID
                            <monster-filter-range></monster-filter-range>
                        </label>

                    </monster-datatable-filter>
                </div>
            </monster-tabs>
        </div>
    </monster-collapse>

    <div slot="bar" class="monster-button-group">
        <monster-embedded-pagination data-monster-datasource-selector="#myDataSourceID"></monster-embedded-pagination>
        <monster-datasource-status
                data-monster-option-datasource-selector="#myDataSourceID"></monster-datasource-status>

        <monster-datatable-filter-button data-monster-reference="#filter-collapse"
                                         data-monster-role="filter-button">Filter
        </monster-datatable-filter-button>
    </div>

    <template id="row">
        <div data-monster-grid-template="1.2rem" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-grid-template="auto" data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-grid-template="3fr" data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="zipcode" data-monster-replace="path:row.zipcode"></div>
        <div data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Sort Data

To enable sorting for individual columns, the attribute data-monster-sortable with the desired field name must be set in the template for the desired column. In this example, the columns id, full_name, country, and username are sortable.

Your individual sorting preferences will then, in the case of a REST data source, be appended to the URL. For example, the URL will look like this:


/example?limit=5&page=${page}&orderBy=${order}

The structure of the query string can be modified using the data-monster-order-template attribute in the respective column in the row template. The default value is ${field} ${direction}. Multiple sorting parameters are separated by commas. The comma delimiter can be changed using the data-monster-datasource-orderdelimiter attribute in the monster-datatable tag.

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";<script type="module">// import "@schukai/monster/source/components/datatable/datatable.mjs";
// import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
// import "@schukai/monster/source/components/form/button.mjs";
// import "@schukai/monster/source/components/form/state-button.mjs";
// import "@schukai/monster/source/components/form/confirm-button.mjs";
// import "@schukai/monster/source/components/form/button-bar.mjs";
// import "@schukai/monster/source/components/form/field-set.mjs";</script>

HTML

<monster-datasource-rest id="myDatasource"
                         data-monster-option-features-autoInit="true"
                         data-monster-option-read-url="/example?limit=5&page=${page}&orderBy=${order}"
></monster-datasource-rest>

<monster-datatable data-monster-datasource-selector="#myDatasource">
    <template id="row">
        <div data-monster-sortable="id" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-sortable="full_name" data-monster-head="full_name" data-monster-replace="path:row.full_name"></div>
        <div data-monster-sortable="country" data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-sortable="username" data-monster-head="username" data-monster-replace="path:row.username"></div>
        <div data-monster-head="registered_date" data-monster-replace="path:row.registered_date"></div>
        <div data-monster-head="status" data-monster-replace="path:row.status"></div>
    </template>
</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Select Rows

This example demonstrates how to implement row selection in a datatable. It is recommended to ensure the selection column remains visible and has a restricted width, though this is optional.

When a user selects a row, an event is triggered that can be listened to and handled as needed. Among the available events, the most relevant is the generic monster-datatable-selection-changed.

To perform actions on selected rows, a button can be displayed once a selection is made. The selected rows can be retrieved using the getSelectedRows() method, which returns their indices. These indices can then be used to fetch the corresponding data from the datasource.

To automatically show and hide the action buttons, the attribute data-monster-role="row-action-button" must be set. To prevent layout issues, the enclosing container should have the CSS class monster-button-group.

ACTION

Javascript

import "@schukai/monster/source/components/datatable/datatable.mjs";
import "@schukai/monster/source/components/datatable/embedded-pagination.mjs";
import "@schukai/monster/source/components/datatable/filter.mjs";
import "@schukai/monster/source/components/form/button.mjs";
import "@schukai/monster/source/components/form/state-button.mjs";
import "@schukai/monster/source/components/form/confirm-button.mjs";
import "@schukai/monster/source/components/form/button-bar.mjs";
import "@schukai/monster/source/components/form/field-set.mjs";

const datatable = document.querySelector("monster-datatable");

const eventHandler = function () {
    const selected = datatable.getSelectedRows();

    // do something with the selected rows
    console.log("Selected rows: ", selected);
}

/**
 * Listen for the selection change event on the datatable.
 */
datatable.addEventListener("monster-datatable-selection-changed", eventHandler);<script type="module">// const actionButton = document.getElementById("cur34-button-1")
// const datatable = document.getElementById("cur34");
//
// const eventHandler = function () {
//     const selected = datatable.getSelectedRows();
// }
//
// datatable.addEventListener("monster-datatable-selection-changed", eventHandler);</script>

HTML

<monster-datasource-dom id="myDatasource">
    <script type="application/json">
        {
            "dataset": [
                {
                    "id": 1,
                    "name": "John Doe",
                    "street": "Main Street 1",
                    "city": "Berlin",
                    "zipcode": "10115",
                    "country": "Germany",
                    "phone": "+49 30 1234.56",
                    "email": "john.doe@example.com"
                },
                {
                    "id": 2,
                    "name": "Jane Doe",
                    "street": "Second Avenue 2",
                    "city": "Munich",
                    "zipcode": "80331",
                    "country": "Germany",
                    "phone": "+49 89 6543.21",
                    "email": "jane.doe@example.com"
                },
                {
                    "id": 3,
                    "name": "Max Mustermann",
                    "street": "Example Road 3",
                    "city": "Hamburg",
                    "zipcode": "20095",
                    "country": "Germany",
                    "phone": "+49 40 1111.11",
                    "email": "max.mustermann@example.com"
                },
                {
                    "id": 4,
                    "name": "Lena Schmidt",
                    "street": "Hauptstrasse 4",
                    "city": "Cologne",
                    "zipcode": "50667",
                    "country": "Germany",
                    "phone": "+49 221 9876.54",
                    "email": "lena.schmidt@example.com"
                },
                {
                    "id": 5,
                    "name": "Markus Meier",
                    "street": "Ringstrasse 5",
                    "city": "Frankfurt",
                    "zipcode": "60311",
                    "country": "Germany",
                    "phone": "+49 69 4321.98",
                    "email": "markus.meier@example.com"
                }
            ]
        }
    </script>
</monster-datasource-dom>

<monster-datatable data-monster-datasource-selector="#myDatasource">

    <div slot="bar" class="monster-button-group">
        <div class="row-action-buttons">
            <monster-button data-monster-role="row-action-button" id="action-button">ACTION</monster-button>
        </div>
    </div>

    <template id="row">
        <div data-monster-grid-template="2rem" data-monster-mode="fixed" data-monster-head="id" data-monster-replace="path:row.id"></div>
        <div data-monster-grid-template="2rem" data-monster-mode="fixed" data-monster-features="select"><input type="checkbox" data-monster-role="select-row"></div>
        <div data-monster-head="name" data-monster-replace="path:row.name"></div>
        <div data-monster-head="street" data-monster-replace="path:row.street"></div>
        <div data-monster-head="city" data-monster-replace="path:row.city"></div>
        <div data-monster-head="country" data-monster-replace="path:row.country"></div>
        <div data-monster-head="phone" data-monster-replace="path:row.phone"></div>
        <div data-monster-head="email" data-monster-replace="path:row.email"></div>
    </template>

</monster-datatable>

Stylesheet

/** no additional stylesheet is defined **/
Open in playground

Component Design

This component is built using the Shadow DOM, which allows it to encapsulate its internal structure and styling. By using a shadow root, the component's internal elements are isolated from the rest of the webpage, ensuring that external styles or scripts cannot accidentally modify its internal layout or behavior.

Shadow DOM and Accessibility

Since the component is encapsulated within a shadow root, direct access to its internal elements is restricted. This means that developers cannot manipulate or style these elements from outside the component. The Shadow DOM helps maintain consistency in the design and behavior of the component by preventing external interference.

Customizing Through Exported Parts

While the Shadow DOM restricts direct access to the component's internal structure, customization is still possible through exported parts. Specific parts of the component are made accessible for styling by being explicitly marked for export. These exported parts can be targeted and customized using CSS, allowing you to modify the appearance of the component without compromising its encapsulation.

Available Part Attributes

  • control: This part represents the entire control area of the slider, including navigation buttons and thumbnails. Use this to style the general layout and background of the control panel.

Below is an example of how to use CSS part attributes to customize different parts of the Control.


monster-button::part(control) {
    background-color: #f0f0f0;
    padding: 10px;
}

Explanation of the Example

  • monster-button::part(control): Styles the entire control panel, giving it a light background color and some padding.

Accessibility

Accessibility is a key consideration in the design of this component. By following best practices for web accessibility, the component ensures that users of all abilities can interact with it effectively. This includes support for keyboard navigation, screen readers, and other assistive technologies to provide an inclusive user experience.

HTML Structure

<monster-data-table></monster-data-table>

JavaScript Initialization

const element = document.createElement('monster-data-table');
document.body.appendChild(element);

Exported

DataTable

Derived from

CustomElement

Options

The Options listed in this section are defined directly within the class. This class is derived from several parent classes, including the CustomElement class. Therefore, it inherits Options from these parent classes. If you cannot find a specific Options in this list, we recommend consulting the documentation of the CustomElement.

Option
Type
Default
Description
templates
object
Template definitions
templates.main
string
undefined
Main template
datasource
object
Datasource configuration
datasource.selector
string
Selector for the datasource
datasource.orderDelimiter
string
,
Order delimiter
mapping
object
Mapping configuration
mapping.data
string
dataset
Data mapping
data
array
undefined
Data
headers
array
undefined
Headers
responsive
object
Responsive configuration
responsive.breakpoint
number
1440
Breakpoint for responsive mode
labels
object
undefined
Labels
labels.theListContainsNoEntries
string
undefined
Label for empty state
classes
object
Classes
classes.container
string
Container class
features
object
Features
features.settings
boolean
true
Settings feature
features.footer
boolean
true
Footer feature
features.autoInit
boolean
true
Auto init feature (init datasource automatically)
features.doubleClickCopyToClipboard
boolean
true
Double click copy to clipboard feature
features.copyAll
boolean
true
Copy all feature
features.help
boolean
true
Help feature
features.resizeable
boolean
undefined
Columns are resizable
copy
object
Copy configuration
copy.delimiter
string
;
Delimiter character
copy.quoteOpen
string
"
Quote open character
copy.quoteClose
string
"
Quote close character
copy.rowBreak
string
Row break character
updater
object
Updater configuration
updater.batchUpdates
boolean
true
Enables batched updater content/attribute updates
templateMapping
object
Template mapping
templateMapping.row-key
string
undefined
Row key
templateMapping.filter-id
string
undefined
Filter id

  • since
  • deprecated

Properties and Attributes

The Properties and Attributes listed in this section are defined directly within the class. This class is derived from several parent classes, including the CustomElement class and ultimately from HTMLElement. Therefore, it inherits Properties and Attributes from these parent classes. If you cannot find a specific Properties and Attributes in this list, we recommend consulting the documentation of the CustomElement.

  • data-monster-options: Sets the configuration options for the collapse component when used as an HTML attribute.
  • data-monster-option-[name]: Sets the value of the configuration option [name] for the collapse component when used as an HTML attribute.

Methods

The methods listed in this section are defined directly within the class. This class is derived from several parent classes, including the CustomElement class and ultimately from HTMLElement. Therefore, it inherits methods from these parent classes. If you cannot find a specific method in this list, we recommend consulting the documentation of the CustomElement.

Behavioral methods

addRow(data)
Parameters
  • data {object}: data
Returns
  • {DataTable}
Events
  • monster-datatable-row-added
Add a row to the datatable
removeRow(index)
Parameters
  • index {number|string}: index
Returns
  • {DataTable}
Events
  • monster-datatable-row-removed
Remove a row from the datatable

Structural methods

getGridElements(selector)
Parameters
  • selector {string}: selector
Returns
  • {NodeList}
getSelectedRows()
Get the row number of the selected rows as an array

Static methods

[instanceSymbol]()
Returns
  • {symbol}
This method is called by the instanceof operator.
getCSSStyleSheet()
Returns
  • {CSSStyleSheet[]}
getTag()
Returns
  • {string}

Lifecycle methods

Lifecycle methods are called by the environment and are usually not intended to be called directly.

[assembleMethodSymbol]()
Returns
  • void
connectedCallback()
Returns
  • {void}
disconnectedCallback()
Returns
  • {void}

Other methods

copyRow(fromIndex,toIndex)
Parameters
  • fromIndex {number|string}: fromIndex
  • toIndex {number|string}: toIndex
Returns
  • {DataTable}
Events
  • monster-datatable-row-copied
Copy a row from the datatable

Events

The component emits the following events:

  • monster-datatable-row-copied
  • monster-datatable-row-removed
  • monster-datatable-row-added
  • monster-datatable-row-selected
  • monster-datatable-row-deselected
  • monster-datatable-all-rows-selected
  • monster-datatable-all-rows-deselected
  • monster-datatable-selection-changed
  • monster-datatable-row-copied
  • monster-datatable-row-removed
  • monster-datatable-row-added

For more information on how to handle events, see the mdn documentation.

The current width of the area is too small to display the content correctly.