import { Component, booleanAttribute, forwardRef, input } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
/** Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive). */
@Component({
selector: 'app-text-input',
styles: [
`
:host {
display: block;
}
input {
inline-size: 100%;
box-sizing: border-box;
}
`,
],
template: `
`,
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TextInputComponent), multi: true },
],
})
export class TextInputComponent implements ControlValueAccessor {
type = input<'text' | 'password' | 'email'>('text');
placeholder = input('');
invalid = input(false);
inputId = input();
/** Set when the paired form-field renders a `-desc` hint, so it gets announced. */
hasDescription = input(false, { transform: booleanAttribute });
value = '';
disabled = false;
onChange: (v: string) => void = () => {};
onTouched: () => void = () => {};
describedBy(): string | null {
const id = this.inputId();
if (!id) return null;
const ids = [
...(this.hasDescription() ? [`${id}-desc`] : []),
...(this.invalid() ? [`${id}-error`] : []),
];
return ids.length ? ids.join(' ') : null;
}
onInput(e: Event) {
this.value = (e.target as HTMLInputElement).value;
this.onChange(this.value);
}
writeValue(v: string) {
this.value = v ?? '';
}
registerOnChange(fn: (v: string) => void) {
this.onChange = fn;
}
registerOnTouched(fn: () => void) {
this.onTouched = fn;
}
setDisabledState(d: boolean) {
this.disabled = d;
}
}