Angular自定义自动完成组件无法通过FormControl获取值问题
问题:Angular自定义自动完成组件无法通过FormControl获取值
我开发了一个带自动完成功能的Angular自定义组件,想用FormControl获取组件的值,但一直拿不到。调用组件的代码如下:
<app-autocomplete-dropdown formControlName="example" [list]="profiloList"></app-autocomplete-dropdown>
尝试访问this.form.controls['example'].value时,无法获取对应的值。表单初始化代码:
public inizialize(): void { this.form = this.formBuilder.group({ example: [null] }); }
自定义组件TS文件
export class AutocompleteDropdownComponent implements ControlValueAccessor { @Input() list: Array<any> = []; selectedElement!: Object; selectedTitle?: String; onChange: any = () => { } onTouch: any = () => { } touched = false; disabled = false; constructor() { } changes(event: Event) { if (this.disabled) return this.markAsTouched() this.selectedElement = event?.target ? (event?.target as HTMLTextAreaElement).value : '' this.onChange(this.selectedElement) } writeValue(obj: any): void { this.selectedElement = obj; } registerOnChange(fn: any): void { this.onChange = fn; } registerOnTouched(fn: any): void { this.onTouch = fn; } setDisabledState?(isDisabled: boolean): void { this.disabled = isDisabled; } markAsTouched() { if (!this.touched) { this.onTouch(); this.touched = true; } } }
自定义组件HTML文件
<input type="text" class="input" list="list" (keyup)="changes($event)"> <i class="bz-chevron-down icon arrow"></i> <datalist id="list"> <option *ngFor="let element of list" [value]="element.objectTitle"> {{element.objectTitle}}</option> </datalist>
解决方案
问题出在3个关键细节上,逐一修正即可解决:
- 替换事件绑定类型
当前使用(keyup)事件,但用户选择datalist选项时不会触发keyup,导致值无法同步到FormControl。改用(input)事件,它能覆盖手动输入和选择选项两种场景:
<input type="text" class="input" list="list" (input)="changes($event)">
- 修正类型匹配与值同步逻辑
selectedElement被声明为Object类型,但实际从input拿到的是字符串(element.objectTitle),类型不匹配,修改为字符串类型:selectedElement!: string;writeValue方法只赋值给selectedElement,没有同步到input的显示值,需要通过模板引用变量+ViewChild实现双向同步:
修改HTML,给input加模板引用:
<input #autocompleteInput type="text" class="input" list="list" (input)="changes($event)">
修改TS代码:
import { ViewChild, ElementRef } from '@angular/core'; export class AutocompleteDropdownComponent implements ControlValueAccessor { @ViewChild('autocompleteInput') autocompleteInput!: ElementRef<HTMLInputElement>; selectedElement!: string; // ...其他代码不变 writeValue(obj: any): void { this.selectedElement = obj || ''; if (this.autocompleteInput) { this.autocompleteInput.nativeElement.value = this.selectedElement; } } changes(event: Event) { if (this.disabled) return this.markAsTouched() // 修正类型为HTMLInputElement(不是textarea) this.selectedElement = event?.target ? (event?.target as HTMLInputElement).value : '' this.onChange(this.selectedElement) } }
- 简化touched状态逻辑
当前touched变量设为true后不会重置,导致后续操作无法触发onTouch()。直接移除状态判断,每次调用都标记为touched:
markAsTouched() { this.onTouch(); }
内容的提问来源于stack exchange,提问作者user18772237
相关产品推荐
相关产品推荐

