upp-input
A reusable text input component that integrates with Angular Reactive Forms. It supports multiple input types (text, email, password, number, price), kiosk mode for touch-based environments, floating labels, and inline validation error display.
When to Use
Use upp-input whenever you need a form field for single-line text entry. It handles common scenarios like password visibility toggling, numeric/price formatting with locale-aware decimal handling, and automatic error rendering when paired with the errornfo property. Prefer it over raw <input> elements to maintain consistent styling and behavior across the application.
Layout: Wrap upp-input in an ion-item so validation errors are positioned correctly (bottom-right). Without ion-item, the error message may not align with the field.
Demo
Source Code
- HTML
- TypeScript
- SCSS
<div class="demo-scroll-container">
<upp-scrollable [scrollbar]="'y'">
<div class="demo-content">
<h2>User Profile</h2>
<p class="demo-description">Edit user details using <code>upp-input</code> with different types and validation.</p>
<div class="demo-controls">
<ion-button size="small" (click)="toggleReadonly()">Readonly: {{ isReadonly }}</ion-button>
<ion-button size="small" (click)="toggleDisabled()">Disabled: {{ isDisabled }}</ion-button>
<ion-button size="small" color="warning" (click)="validate()">Validate</ion-button>
<ion-button size="small" color="medium" (click)="resetForm()">Reset</ion-button>
</div>
<p class="demo-hint">Validation errors appear when the field is touched (blur) or dirty. Leave required fields empty and blur to see errors.</p>
<div class="demo-section" [formGroup]="form">
<h3>Personal Information</h3>
<ion-list lines="none">
<ion-item>
<upp-input
formControlName="name"
placeholder="John Doe"
title="Full Name (required, min 3 chars)"
[readonly]="isReadonly"
[kiosk]="false"
[errornfo]="errorMessages">
</upp-input>
</ion-item>
<ion-item>
<upp-input
formControlName="email"
placeholder="john@company.com"
title="Email (required)"
type="email"
[readonly]="isReadonly"
[kiosk]="false"
[errornfo]="errorMessages">
</upp-input>
</ion-item>
<ion-item>
<upp-input
formControlName="phone"
placeholder="612345678"
title="Phone"
type="number"
[readonly]="isReadonly"
[kiosk]="false">
</upp-input>
</ion-item>
</ion-list>
<h3>Compensation</h3>
<ion-list lines="none">
<ion-item>
<upp-input
formControlName="rate"
placeholder="0.00"
title="Hourly Rate (currency format)"
type="price"
[readonly]="isReadonly"
[kiosk]="false">
</upp-input>
</ion-item>
</ion-list>
<h3>Security</h3>
<ion-list lines="none">
<ion-item>
<upp-input
formControlName="pin"
placeholder="****"
title="PIN"
type="password"
[readonly]="isReadonly"
[kiosk]="false">
</upp-input>
</ion-item>
</ion-list>
</div>
</div>
</upp-scrollable>
</div>
import { Component, OnInit } from '@angular/core';
import { ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
@Component({
selector: 'demo-upp-input',
templateUrl: './demo-upp-input.html',
styleUrls: ['../demo-common.scss', './demo-upp-input.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DemoUppInputComponent implements OnInit {
form!: FormGroup;
isReadonly = false;
isDisabled = false;
errorMessages: Record<string, string> = {
required: 'This field is required',
minlength: 'Minimum 3 characters',
email: 'Invalid email format',
};
constructor(private change: ChangeDetectorRef) {
}
ngOnInit() {
this.form = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(3)]),
email: new FormControl('', [Validators.required, Validators.email]),
phone: new FormControl(''),
rate: new FormControl(''),
pin: new FormControl(''),
});
}
toggleReadonly() {
this.isReadonly = !this.isReadonly;
this.change.markForCheck();
}
toggleDisabled() {
this.isDisabled = !this.isDisabled;
if (this.isDisabled) {
this.form.disable();
} else {
this.form.enable();
}
this.change.markForCheck();
}
validate() {
Object.values(this.form.controls).forEach(c => {
c.markAsTouched();
c.markAsDirty();
});
this.change.markForCheck();
}
resetForm() {
this.form.reset();
this.isReadonly = false;
this.isDisabled = false;
this.form.enable();
this.change.markForCheck();
}
}
:host {
display: block;
height: 100vh;
}
API Reference
UppInputComponent (upp-input)
The main input component. Wraps upp-kb-input (the keyboard-level input) and upp-er-input (inline error display) into a single, form-ready widget.
Inputs
| Property | Type | Default | Description |
|---|---|---|---|
placeholder | string | '' | Placeholder text shown when the field is empty. |
formControlName | string | '' | Name of the reactive form control this input binds to. |
readonly | boolean | false | When true, the input is read-only. |
disabled | boolean | false | When true, the input is disabled. Also respects the parent FormGroup disabled state. |
type | string | '' | Input type: text, email, password, number, or price. |
kiosk | boolean | true | Enables kiosk mode (on-screen keyboard) when the platform reports kiosk. |
title | string | '' | Floating label text displayed above the input when it has a value. Falls back to placeholder if empty. |
autocomplete | string | 'off' | HTML autocomplete attribute value. |
errornfo | Record<string, string> | {} | Map of validation error keys to human-readable messages. Errors are shown when the control is dirty or touched. |
value | string | null | null | The current value of the input (two-way via ControlValueAccessor). |
Outputs
| Event | Payload | Description |
|---|---|---|
Changed | string | null | Emitted when the value changes. |
Focus | void | Emitted when the input gains focus. |