FRAMEWORKS
Plain HTML
The components are standard custom elements, so they work in a plain HTML page with no framework and no build step. Write the tags in HTML, set rich data from JavaScript, and listen for events with addEventListener.
Load from a CDN
An import map tells the browser where each package lives. esm.sh serves every package as an ES module and resolves its dependencies, Lit among them. Add one entry for each package you use, then import it:
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@dojo-ng/theme/theme.css">
<script type="importmap">
{
"imports": {
"@dojo-ng/select": "https://esm.sh/@dojo-ng/select",
"@dojo-ng/chip": "https://esm.sh/@dojo-ng/chip"
}
}
</script>
<script type="module">
import "@dojo-ng/select";
import "@dojo-ng/chip";
</script>
</head>
<body>
<dj-select label="Plan"></dj-select>
<dj-chip closeable>design</dj-chip>
</body>
</html>
- A page can have only one import map, and it must come before any module script.
- Without a version, esm.sh serves the latest release. To stay on one version, add it to the URL:
"@dojo-ng/select": "https://esm.sh/@dojo-ng/select@0.1.2"
Use a bundler
With Vite, webpack, Rollup, or esbuild, install the packages from npm and import them in your entry file. The bundler resolves the imports, so no import map is needed:
// npm install @dojo-ng/select @dojo-ng/chip
import "@dojo-ng/select";
import "@dojo-ng/chip";
Properties and attributes
Attributes hold text, so arrays and objects must be set as properties from JavaScript. Strings, numbers, and booleans work either way.
<dj-select id="plan" label="Plan" value="free"></dj-select>
<script type="module">
import "@dojo-ng/select";
const plan = document.getElementById("plan");
// Arrays, objects, and functions: set the property
plan.options = [
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
];
// Strings, numbers, and booleans: an attribute or the property, either works
plan.setAttribute("label", "Your plan");
plan.required = true;
plan.addEventListener("change", () => console.log("plan is now", plan.value));
</script>
- A property set before the package loads is kept. The component picks it up when it is defined.
- A boolean attribute is true when it is present, whatever its value. To turn it off, remove the attribute or set the property to
false. - The API reference lists each property and its attribute name.
Events
<div id="tags">
<dj-chip closeable>design</dj-chip>
<dj-chip closeable>docs</dj-chip>
</div>
<script type="module">
import "@dojo-ng/chip";
// One listener on the container hears every chip, because the events bubble
document.getElementById("tags").addEventListener("dj-close", (event) => {
event.target.remove();
});
</script>
- The
dj-*events bubble and cross shadow roots, so one listener on a container hears all of its components. - The event data is in
event.detail. Each component's API page lists its events.
Wait for a component
Code that runs before a package loads sees an element with no behavior yet. When you need the component ready, wait for its definition, and for its first render if you read its shadow DOM:
await customElements.whenDefined("dj-select");
const plan = document.getElementById("plan");
await plan.updateComplete; // the first render is done
plan.shadowRoot.querySelector("[part=trigger]");
Forms
The controls are form-associated, so a plain <form> submits their values and checks their rules like built-in inputs. See Forms & validation.