Run the CLI
Use the CLI to add the component to your project.
npx @ngzard/ui@latest add inputDisplays a form input field or a component that looks like an input field.
import { Component } from '@angular/core';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-default',
imports: [ZardInputDirective],
standalone: true,
template: `
<input z-input placeholder="Default" />
<input z-input disabled placeholder="Disabled" />
`,
})
export class ZardDemoInputDefaultComponent {}
Use the CLI to add the component to your project.
npx @ngzard/ui@latest add inputpnpm dlx @ngzard/ui@latest add inputyarn dlx @ngzard/ui@latest add inputbunx @ngzard/ui@latest add inputCreate the component directory structure and add the following files to your project.
import { computed, Directive, effect, ElementRef, inject, input, linkedSignal, model } from '@angular/core';
import type { ClassValue } from 'clsx';
import {
inputVariants,
type ZardInputSizeVariants,
type ZardInputStatusVariants,
type ZardInputTypeVariants,
} from './input.variants';
import { mergeClasses, transform } from '../../shared/utils/utils';
@Directive({
selector: 'input[z-input], textarea[z-input]',
host: {
'[class]': 'classes()',
'(input)': 'updateValue($event.target)',
},
exportAs: 'zInput',
})
export class ZardInputDirective {
private readonly elementRef = inject(ElementRef);
readonly class = input<ClassValue>('');
readonly zBorderless = input(false, { transform });
readonly zSize = input<ZardInputSizeVariants>('default');
readonly zStatus = input<ZardInputStatusVariants>();
readonly value = model<string>('');
readonly size = linkedSignal<ZardInputSizeVariants>(() => this.zSize());
protected readonly classes = computed(() =>
mergeClasses(
inputVariants({
zType: this.getType(),
zSize: this.size(),
zStatus: this.zStatus(),
zBorderless: this.zBorderless(),
}),
this.class(),
),
);
constructor() {
effect(() => {
const value = this.value();
if (value !== undefined && value !== null) {
this.elementRef.nativeElement.value = value;
}
});
}
disable(b: boolean): void {
this.elementRef.nativeElement.disabled = b;
}
setDataSlot(name: string): void {
if (this.elementRef?.nativeElement?.dataset) {
this.elementRef.nativeElement.dataset.slot = name;
}
}
protected updateValue(target: EventTarget | null): void {
const el = target as HTMLInputElement | HTMLTextAreaElement | null;
this.value.set(el?.value ?? '');
}
getType(): ZardInputTypeVariants {
const isTextarea = this.elementRef.nativeElement.tagName.toLowerCase() === 'textarea';
return isTextarea ? 'textarea' : 'default';
}
}
import { cva, type VariantProps } from 'class-variance-authority';
export type zInputIcon = 'email' | 'password' | 'text';
export const inputVariants = cva('w-full', {
variants: {
zType: {
default:
'flex rounded-md border px-4 font-normal border-input bg-transparent file:border-0 file:text-foreground file:bg-transparent file:font-medium placeholder:text-muted-foreground outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
textarea:
'flex pb-2 min-h-20 h-auto rounded-md border border-input bg-background px-3 py-2 text-base placeholder:text-muted-foreground outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
},
zSize: {
default: 'text-sm',
sm: 'text-xs',
lg: 'text-base',
},
zStatus: {
error: 'border-destructive focus-visible:ring-destructive',
warning: 'border-yellow-500 focus-visible:ring-yellow-500',
success: 'border-green-500 focus-visible:ring-green-500',
},
zBorderless: {
true: 'flex-1 bg-transparent border-0 outline-none focus-visible:ring-0 focus-visible:ring-offset-0 px-0 py-0',
},
},
defaultVariants: {
zType: 'default',
zSize: 'default',
},
compoundVariants: [
{ zType: 'default', zSize: 'default', class: 'h-9 py-2 file:max-md:py-0' },
{ zType: 'default', zSize: 'sm', class: 'h-8 file:md:py-2 file:max-md:py-1.5' },
{ zType: 'default', zSize: 'lg', class: 'h-10 py-1 file:md:py-3 file:max-md:py-2.5' },
],
});
export type ZardInputTypeVariants = NonNullable<VariantProps<typeof inputVariants>['zType']>;
export type ZardInputSizeVariants = NonNullable<VariantProps<typeof inputVariants>['zSize']>;
export type ZardInputStatusVariants = NonNullable<VariantProps<typeof inputVariants>['zStatus']>;
import { Component } from '@angular/core';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-default',
imports: [ZardInputDirective],
standalone: true,
template: `
<input z-input placeholder="Default" />
<input z-input disabled placeholder="Disabled" />
`,
})
export class ZardDemoInputDefaultComponent {}
import { Component } from '@angular/core';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-size',
imports: [ZardInputDirective],
standalone: true,
template: `
<input z-input zSize="sm" placeholder="small size" />
<input z-input zSize="default" placeholder="default size" />
<input z-input zSize="lg" placeholder="large size" />
`,
})
export class ZardDemoInputSizeComponent {}
import { Component } from '@angular/core';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-status',
imports: [ZardInputDirective],
standalone: true,
template: `
<input z-input zStatus="error" placeholder="Error" />
<input z-input zStatus="warning" placeholder="Warning" />
<input z-input zStatus="success" placeholder="Success" />
`,
})
export class ZardDemoInputStatusComponent {}
import { Component } from '@angular/core';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-borderless',
imports: [ZardInputDirective],
standalone: true,
template: `<input z-input zBorderless placeholder="Borderless" />`,
})
export class ZardDemoInputBorderlessComponent {}
import { Component } from '@angular/core';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-text-area',
imports: [ZardInputDirective],
standalone: true,
template: `
<textarea z-input rows="8" cols="12" placeholder="Default"></textarea>
<textarea zBorderless z-input rows="8" cols="12" placeholder="Borderless"></textarea>
`,
})
export class ZardDemoInputTextAreaComponent {}