input

Displays a form input field or a component that looks like an input field.

PreviousNext

Your API key is encrypted and stored securely.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-preview',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="input-demo-api-key">API Key</label>
      <input z-input id="input-demo-api-key" type="password" placeholder="sk-..." />
      <p z-field-description>Your API key is encrypted and stored securely.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputPreviewComponent {}

Installation

Copy
npx zard-cli@latest add input

Usage

import { ZardInputComponent } from '@/shared/components/input/input.component';
Copy
<input z-input type="email" placeholder="Email" />
Copy

Examples

basic

Use input[z-input] on its own for a simple, unlabeled input.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-basic',
  imports: [ZardInputComponent],
  template: `
    <input z-input id="input-basic" placeholder="Enter text" class="w-72" />
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputBasicComponent {}

field

Wrap input[z-input] in z-field with a z-field-label and z-field-description to add a label and helper text.

Choose a unique username for your account.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-field',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="input-field-username">Username</label>
      <input z-input id="input-field-username" type="text" placeholder="Enter your username" />
      <p z-field-description>Choose a unique username for your account.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputFieldComponent {}

field group

Stack multiple z-field blocks inside z-field-group to build a mini form, and set zOrientation="horizontal" on the last one to lay the action buttons out in a row.

We'll send updates to this address.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-field-group',
  imports: [ZardInputComponent, ZardButtonComponent, ...ZardFieldImports],
  template: `
    <div z-field-group class="w-72">
      <div z-field>
        <label z-field-label for="fieldgroup-name">Name</label>
        <input z-input id="fieldgroup-name" placeholder="Jordan Lee" />
      </div>
      <div z-field>
        <label z-field-label for="fieldgroup-email">Email</label>
        <input z-input id="fieldgroup-email" type="email" placeholder="name@example.com" />
        <p z-field-description>We'll send updates to this address.</p>
      </div>
      <div z-field zOrientation="horizontal">
        <button z-button type="reset" zType="outline">Reset</button>
        <button z-button type="submit">Submit</button>
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputFieldGroupComponent {}

disabled

Set the native disabled attribute on input[z-input], and add data-disabled="true" to the surrounding z-field so its label and description dim along with the control.

This field is currently disabled.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-disabled',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72" data-disabled="true">
      <label z-field-label for="input-demo-disabled">Email</label>
      <input z-input id="input-demo-disabled" type="email" placeholder="Email" disabled />
      <p z-field-description>This field is currently disabled.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputDisabledComponent {}

invalid

Set aria-invalid="true" on input[z-input] and data-invalid="true" on the surrounding z-field to mark the field as invalid; see the form example for wiring these attributes to a reactive form control.

This field contains validation errors.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-invalid',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72" data-invalid="true">
      <label z-field-label for="input-invalid">Invalid Input</label>
      <input z-input id="input-invalid" placeholder="Error" aria-invalid="true" />
      <p z-field-description>This field contains validation errors.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputInvalidComponent {}

file

Set type="file" on input[z-input] to create a file picker.

Select a picture to upload.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-file',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="picture">Picture</label>
      <input z-input id="picture" type="file" />
      <p z-field-description>Select a picture to upload.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputFileComponent {}

inline

Set zOrientation="horizontal" on z-field to lay the input and a z-button out in a row, for example to pair a search input with a submit button.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-inline',
  imports: [ZardInputComponent, ZardButtonComponent, ...ZardFieldImports],
  template: `
    <div z-field zOrientation="horizontal" class="w-80">
      <input z-input id="input-inline-search" type="search" placeholder="Search..." />
      <button type="button" z-button>Search</button>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputInlineComponent {}

grid

Use a grid layout class on z-field-group to place multiple z-fields side by side.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-grid',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field-group class="grid min-w-sm grid-cols-2">
      <div z-field>
        <label z-field-label for="first-name">First Name</label>
        <input z-input id="first-name" placeholder="Jordan" />
      </div>
      <div z-field>
        <label z-field-label for="last-name">Last Name</label>
        <input z-input id="last-name" placeholder="Lee" />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputGridComponent {}

required

Set the native required attribute on input[z-input], and add a visual required marker inside z-field-label.

This field must be filled out.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-required',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="input-required">
        Required Field
        <span class="text-destructive">*</span>
      </label>
      <input z-input id="input-required" placeholder="This field is required" required />
      <p z-field-description>This field must be filled out.</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputRequiredComponent {}

badge

Place a z-badge inside z-field-label to highlight a recommended field.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardBadgeComponent } from '@/shared/components/badge/badge.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-badge',
  imports: [ZardInputComponent, ZardBadgeComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-80">
      <label z-field-label for="input-badge">
        Webhook URL
        <z-badge zType="secondary" class="ml-auto">Beta</z-badge>
      </label>
      <input z-input id="input-badge" type="url" placeholder="https://api.example.com/webhook" />
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputBadgeComponent {}

input group

To add icons, text or buttons inside the input, wrap it in z-input-group. See the Input Group component for more examples.
https://
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideInfo } from '@ng-icons/lucide';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { ZardInputGroupImports } from '@/shared/components/input-group/input-group.imports';

@Component({
  selector: 'z-demo-input-input-group',
  imports: [ZardInputComponent, NgIcon, ...ZardInputGroupImports, ...ZardFieldImports],
  template: `
    <div z-field class="w-80">
      <label z-field-label for="input-group-url">Website URL</label>
      <z-input-group>
        <z-input-group-addon>
          <span z-input-group-text>https://</span>
        </z-input-group-addon>
        <input z-input id="input-group-url" placeholder="example.com" />
        <z-input-group-addon zAlign="inline-end">
          <ng-icon name="lucideInfo" />
        </z-input-group-addon>
      </z-input-group>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  viewProviders: [provideIcons({ lucideInfo })],
})
export class ZardDemoInputInputGroupComponent {}

button group

To add a button next to the input, wrap both in z-button-group. See the Button Group component for more examples.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardButtonGroupComponent } from '@/shared/components/button-group/button-group.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-input-button-group',
  imports: [ZardInputComponent, ZardButtonComponent, ZardButtonGroupComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-80">
      <label z-field-label for="input-button-group">Search</label>
      <z-button-group>
        <input z-input id="input-button-group" placeholder="Type to search..." />
        <button type="button" z-button zType="outline">Search</button>
      </z-button-group>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputButtonGroupComponent {}

form

A full reactive form built from z-field-group and z-field, with z-select for the country and a live validation message on the email field once it's touched and invalid.

We'll never share your email with anyone.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { ZardSelectImports } from '@/shared/components/select/select.imports';

@Component({
  selector: 'z-demo-input-form',
  imports: [ZardInputComponent, ZardButtonComponent, ZardSelectImports, ReactiveFormsModule, ...ZardFieldImports],
  template: `
    <form class="w-full min-w-sm" [formGroup]="form" (ngSubmit)="onSubmit()">
      <div z-field-group>
        <div z-field>
          <label z-field-label for="form-name">Name</label>
          <input z-input id="form-name" type="text" placeholder="Evil Rabbit" formControlName="name" />
        </div>
        @let emailControl = form.controls.email;
        @let emailInvalid = emailControl.invalid && emailControl.touched;
        <div z-field [attr.data-invalid]="emailInvalid || null">
          <label z-field-label for="form-email">Email</label>
          <input
            z-input
            id="form-email"
            type="email"
            placeholder="john@example.com"
            formControlName="email"
            [attr.aria-invalid]="emailInvalid || null"
          />
          @if (emailInvalid) {
            <z-field-error>
              @if (emailControl.hasError('required')) {
                Email is required.
              } @else if (emailControl.hasError('email')) {
                Enter a valid email address.
              }
            </z-field-error>
          } @else {
            <p z-field-description>We'll never share your email with anyone.</p>
          }
        </div>
        <div class="grid grid-cols-2 gap-4">
          <div z-field>
            <label z-field-label for="form-phone">Phone</label>
            <input z-input id="form-phone" type="tel" placeholder="+1 (555) 123-4567" formControlName="phone" />
          </div>
          <div z-field>
            <label z-field-label for="form-country">Country</label>
            <z-select id="form-country" formControlName="country">
              <z-select-item zValue="us">United States</z-select-item>
              <z-select-item zValue="uk">United Kingdom</z-select-item>
              <z-select-item zValue="ca">Canada</z-select-item>
            </z-select>
          </div>
        </div>
        <div z-field>
          <label z-field-label for="form-address">Address</label>
          <input z-input id="form-address" type="text" placeholder="123 Main St" formControlName="address" />
        </div>
        <div z-field zOrientation="horizontal">
          <button z-button type="button" zType="outline" (click)="onReset()">Cancel</button>
          <button z-button type="submit">Submit</button>
        </div>
      </div>
    </form>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputFormComponent {
  readonly form = new FormGroup({
    name: new FormControl('', { nonNullable: true, validators: [Validators.required] }),
    email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email] }),
    phone: new FormControl(''),
    country: new FormControl('us'),
    address: new FormControl(''),
  });

  onSubmit(): void {
    this.form.markAllAsTouched();
    if (this.form.valid) {
      console.log('Form submitted:', this.form.getRawValue());
    }
  }

  onReset(): void {
    this.form.reset({ country: 'us' });
  }
}

rtl

To enable RTL support in zard/ui, see the RTL configuration guide.

اختر اسم مستخدم فريدًا لحسابك.

// You will notice this example is rendered inside a wrapper that sets the dir and data-lang attributes, and
// reads its text from a translations helper. This is because this site is not RTL by default.
// In your application you won't need either: set dir="rtl" on <html> (or use the CDK Dir directive on a subtree)
// and write the text of your own language. See the RTL guide: https://zardui.com/docs/rtl

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { injectRtlTranslation, type ZardRtlTranslations } from '@/shared/demo-utils/rtl-translation';

const translations: ZardRtlTranslations<{ label: string; placeholder: string; description: string }> = {
  en: {
    dir: 'ltr',
    values: {
      label: 'Username',
      placeholder: 'Enter your username',
      description: 'Choose a unique username for your account.',
    },
  },
  ar: {
    dir: 'rtl',
    values: {
      label: 'اسم المستخدم',
      placeholder: 'أدخل اسم المستخدم',
      description: 'اختر اسم مستخدم فريدًا لحسابك.',
    },
  },
  he: {
    dir: 'rtl',
    values: {
      label: 'שם משתמש',
      placeholder: 'הזן את שם המשתמש',
      description: 'בחר שם משתמש ייחודי לחשבון שלך.',
    },
  },
};

@Component({
  selector: 'z-demo-input-rtl',
  imports: [ZardInputComponent, ...ZardFieldImports],
  template: `
    <div z-field class="w-72">
      <label z-field-label for="input-rtl-username">{{ i18n.t().label }}</label>
      <input z-input id="input-rtl-username" type="text" [placeholder]="i18n.t().placeholder" />
      <p z-field-description>{{ i18n.t().description }}</p>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputRtlComponent {
  protected readonly i18n = injectRtlTranslation(translations);
}

API Reference

input[z-input]Component

A directive that styles a native `<input>` element. All native HTML input attributes (`type`, `placeholder`, `disabled`, `required`, `readonly`, `aria-invalid`, etc.) keep working as-is.

PropertyDescriptionTypeDefault
[class] Additional CSS classes ClassValue ''
[value] Input value, two-way bindable string | number | null null
[(value)] Input value (two-way binding) string | number | null null
github iconwhatsapp icondiscord iconX icon

Made with ❤ in Brazil. Open source and available on GitHub .