projects/cobbler-frontend/src/app/common/text-autocomplete/text-autocomplete.component.ts
ControlValueAccessor
OnInit
OnChanges
| providers |
TextAutocompleteComponent
|
| selector | cobbler-text-autocomplete |
| standalone | true |
| imports |
MatInput
MatAutocompleteModule
MatFormFieldModule
|
| styleUrls | ./text-autocomplete.component.scss |
| templateUrl | ./text-autocomplete.component.html |
| styleUrl | ./text-autocomplete.component.scss |
MatInput
MatAutocompleteModule
ReactiveFormsModule
AsyncPipe
MatFormFieldModule
HelpButtonComponent
ControlValueAccessor
OnInit
OnChanges
Properties |
Methods |
Inputs |
| hint | |
Type : string
|
|
| label | |
Type : string
|
|
Default value : ''
|
|
| options | |
Type : string[]
|
|
Default value : []
|
|
| readonly | |
Type : boolean
|
|
Default value : false
|
|
| Private _filter | ||||||
_filter(value: string)
|
||||||
|
Parameters :
Returns :
string[]
|
| ngOnChanges | ||||||
ngOnChanges(changes: SimpleChanges)
|
||||||
|
Parameters :
Returns :
void
|
| ngOnInit |
ngOnInit()
|
|
Returns :
void
|
| registerOnChange | ||||||
registerOnChange(fn: (value: string | null) => void)
|
||||||
|
Parameters :
Returns :
void
|
| registerOnTouched | ||||||
registerOnTouched(fn: () => void)
|
||||||
|
Parameters :
Returns :
void
|
| setDisabledState | ||||||
setDisabledState(isDisabled: boolean)
|
||||||
|
Parameters :
Returns :
void
|
| writeValue | ||||||
writeValue(value: string)
|
||||||
|
Parameters :
Returns :
void
|
| filteredOptions |
Type : Observable<string[]>
|
| innerControl |
Type : unknown
|
Default value : new FormControl('')
|
| isDisabled |
Type : unknown
|
Default value : false
|
| onChange |
Type : function
|
Default value : () => {...}
|
| onTouched |
Type : function
|
Default value : () => {...}
|
import { Component, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Input } from '@angular/core';
import {
ControlValueAccessor,
FormControl,
NG_VALUE_ACCESSOR,
ReactiveFormsModule,
} from '@angular/forms';
import { Observable } from 'rxjs';
import { MatInput } from '@angular/material/input';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { AsyncPipe } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { map, startWith } from 'rxjs';
import { HelpButtonComponent } from '../help-button/help-button.component';
@Component({
selector: 'cobbler-text-autocomplete',
imports: [
MatInput,
MatAutocompleteModule,
ReactiveFormsModule,
AsyncPipe,
MatFormFieldModule,
HelpButtonComponent,
],
providers: [
{
provide: NG_VALUE_ACCESSOR,
multi: true,
useExisting: TextAutocompleteComponent,
},
],
templateUrl: './text-autocomplete.component.html',
styleUrl: './text-autocomplete.component.scss',
})
export class TextAutocompleteComponent
implements ControlValueAccessor, OnInit, OnChanges
{
@Input() label: string = '';
@Input() options: string[] = [];
@Input() readonly = false;
@Input() hint?: string;
innerControl = new FormControl('');
filteredOptions: Observable<string[]>;
isDisabled = false;
onChange: (value: string | null) => void = () => {};
onTouched: () => void = () => {};
ngOnInit(): void {
this.filteredOptions = this.innerControl.valueChanges.pipe(
startWith(''),
map((value) => this._filter(value || '')),
);
this.innerControl.valueChanges.subscribe((value) => {
this.onChange(value);
this.onTouched;
});
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['options'] && !changes['options'].firstChange) {
this.innerControl.updateValueAndValidity;
}
}
private _filter(value: string): string[] {
const filterValue = value.toLowerCase();
return this.options.filter((option) =>
option.toLowerCase().includes(filterValue),
);
}
writeValue(value: string): void {
this.innerControl.setValue(value ?? '', { emitEvent: false });
}
registerOnChange(fn: (value: string | null) => void): void {
this.onChange = fn;
}
registerOnTouched(fn: () => void): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
if (isDisabled) {
this.innerControl.disable({ emitEvent: false });
} else {
this.innerControl.enable({ emitEvent: false });
}
}
}
<mat-form-field class="form-field-full-width">
<mat-label>{{ label }}</mat-label>
<input
type="text"
matInput
[formControl]="innerControl"
[readonly]="readonly"
[matAutocomplete]="auto"
/>
<mat-autocomplete #auto="matAutocomplete">
@for (option of filteredOptions | async; track option) {
<mat-option [value]="option">{{ option }}</mat-option>
}
</mat-autocomplete>
@if (hint) {
<cobbler-help-button matSuffix [hint]="hint" />
}
</mat-form-field>
./text-autocomplete.component.scss
:host {
display: flex;
flex-direction: column;
width: 100%;
}