Get started
Standalone components on Angular 22 — zoneless, signal forms, SSR-ready. Three steps from an empty app to a validated field, and a fourth if you render on the server.
Install
npm install @pacit/componentsNo
zone.jsanywhere in the tree — the package refuses it by gate, not by convention.Provide
The library reads one optional config for defaults; the application stays the owner of policy — locale, texts, theme.
import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core'; import { providePctConfig } from '@pacit/components'; export const appConfig: ApplicationConfig = { providers: [ provideZonelessChangeDetection(), providePctConfig({ defaultSize: 'md' }), ], };A first form
Signal forms end to end: the model is a signal, the schema is a function, the field wrapper wires the label, hint and error lines.
import { Component, signal } from '@angular/core'; import { FormField, form, required } from '@angular/forms/signals'; import { PctField, PctText } from '@pacit/components/field'; /** The first form: a model that is a signal, a schema that is a function, one required rule. */ @Component({ selector: 'app-first-form', imports: [FormField, PctField, PctText], template: ` <pct-field label="Workspace name" hint="Lowercase, dashes allowed"> <input pctText [formField]="settings.name" /> </pct-field> `, }) export class FirstForm { readonly model = signal({ name: '' }); readonly settings = form(this.model, (path) => { required(path.name, { message: 'Every workspace needs a name' }); }); }The component above, running. Tab out of the field while it is empty and the schema's own message is what you hear. Server-side rendering
Every component hydrates cleanly — the sandbox suite measures it per view, in three engines. One line more than step 2, and this documentation site is itself prerendered from the same package.
import { ApplicationConfig, provideZonelessChangeDetection } from '@angular/core'; import { provideClientHydration } from '@angular/platform-browser'; import { providePctConfig } from '@pacit/components'; export const appConfig: ApplicationConfig = { providers: [ provideZonelessChangeDetection(), provideClientHydration(), providePctConfig({ defaultSize: 'md' }), ], };
You should see
- the field with its label above it and its hint below, at the size the config set
- tabbing out of it empty names the error, and the input points at that line with
aria-describedby - the page hydrating with nothing in the console — no
zone.js, no mismatch
Next: the components · theming