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.

  1. Install

    npm install @pacit/components

    No zone.js anywhere in the tree — the package refuses it by gate, not by convention.

  2. 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' }),
      ],
    };
  3. 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.
  4. 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