FRAMEWORKS
Angular
Angular binds properties and events on custom elements with its usual syntax. Add CUSTOM_ELEMENTS_SCHEMA so the template compiler accepts the dj-* tags, and add ngDefaultControl to use the text inputs with Angular forms.
Install and register
npm install @dojo-ng/select @dojo-ng/chip @dojo-ng/text-input @dojo-ng/checkbox
Each package registers its tag when you import it. Import the packages once, in main.ts:
// main.ts: import the components once, before bootstrapping
import "@dojo-ng/select";
import "@dojo-ng/chip";
import "@dojo-ng/text-input";
import "@dojo-ng/checkbox";
import { bootstrapApplication } from "@angular/platform-browser";
import { AppComponent } from "./app/app.component";
bootstrapApplication(AppComponent);
An example
Each component that uses dj-* tags needs CUSTOM_ELEMENTS_SCHEMA in its schemas. Without it, the template compiler reports the tags as unknown elements.
import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from "@angular/core";
@Component({
selector: "app-root",
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<dj-select
label="Plan"
[options]="plans"
[value]="plan()"
(change)="plan.set($any($event.target).value)"
></dj-select>
<dj-checkbox
[checked]="agree()"
(change)="agree.set($any($event.target).checked)"
>I agree</dj-checkbox>
@for (tag of tags(); track tag) {
<dj-chip closeable (dj-close)="remove(tag)">{{ tag }}</dj-chip>
}
`,
})
export class AppComponent {
plans = [
{ value: "free", label: "Free" },
{ value: "pro", label: "Pro" },
];
plan = signal("free");
agree = signal(false);
tags = signal(["design", "docs"]);
remove(tag: string) {
this.tags.update((tags) => tags.filter((t) => t !== tag));
}
}
Properties and attributes
[name]="value"sets the property, so arrays and objects arrive as they are, such as[options]="plans". This works even when the tag renders before its package is imported.- A plain attribute, such as
label="Plan"orcloseable, works as in HTML. - Use
[attr.name]only when you need an attribute, such as anaria-*value.
Events
- Listen for a Dojo NG event by its exact name, with the dash:
(dj-close),(dj-submit),(dj-select). - Standard events work as usual:
(input),(change), and(click). - The event data is in
$event.detail.$event.targetis typed as a plainEventTarget, so the example uses$any()to readvalueandchecked.
ngModel and reactive forms
Angular's forms attach only to the native inputs they know. Add ngDefaultControl to a Dojo NG text input, and [(ngModel)], [formControl], and formControlName work with it:
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import { FormControl, FormsModule, ReactiveFormsModule } from "@angular/forms";
@Component({
selector: "app-profile",
imports: [FormsModule, ReactiveFormsModule],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<dj-text-input label="Name" ngDefaultControl [(ngModel)]="name"></dj-text-input>
<dj-text-input label="Email" ngDefaultControl [formControl]="email"></dj-text-input>
`,
})
export class ProfileComponent {
name = "";
email = new FormControl("");
}
ngDefaultControlworks with controls that have avalueproperty and emitinput: the text inputs and the text area.- For a checkbox, switch, or select, bind
[checked]or[value]and update it in(change), as in the example above. - Validation through Angular forms comes from your validators. The browser's own checks, such as
requiredon a Dojo NG control, apply to a native<form>. See Forms & validation.