Я пытаюсь преобразовать текстовое поле ввода, которое имитирует выпадающий список с автозаполнением. Когда пользователь введет в текстовое поле хотя бы два символа, я хочу отобразить отфильтрованный список объектов, которые начинаются с введенных символов.
Используя шаблонные формы, я имел это в виду:
<div class="form-group">
<label>What do you do for a living? <a href="#" class="tooltip" title="Your job help"><span></span></a></label>
<input type="text" class="form-control"
placeholder="Type the first two letters"
[(ngModel)]="filteredOccupationInput"/>
</div>
<div *ngIf="filteredOccupations && filteredOccupationInput.length > 1">
<p *ngFor="let filteredOccupation of filteredOccupations">
{{ filteredOccupation.occupationText }}
</p>
</div>
В самом компоненте у меня есть
private occupationFilterInput = '';
...
get filteredOccupationInput(): string {
return this.occupationFilterInput;
}
set filteredOccupationInput(value: string) {
this.occupationFilterInput = value;
this.filteredOccupations = this.filteredOccupationInput ?
this.performFilterOccupation(this.filteredOccupationInput) :
this.occupations;
}
filteredOccupations: OccupationDto[] = [];
occupations: OccupationDto[] = [];
...
// Other logic omitted for brevity
performFilterOccupation(filterBy: string): OccupationDto[] {
filterBy = filterBy.toLocaleLowerCase();
return this.occupations.filter( (occupation: OccupationDto) =>
occupation.occupationText.toLocaleLowerCase().startsWith(filterBy) === true);
}
Для завершения DTO, которое я использую, выглядит следующим образом ...
export interface OccupationDto {
occupationCode: string;
occupationText: string;
}
Я добавил обычную логику для FormBuilder и добавил привязку [FormGroup] в верхней части формы, а также formControlName к входному текстовому полю HTML оставив ngModel на месте, чтобы в моем HTML было следующее:
<div class="form-group">
<label>What do you do for a living? <a href="#" class="tooltip" title="Your job help"><span></span></a></label>
<input type="text" class="form-control" formControlName="filteredOccupationInput"
placeholder="Type the first two letters"
[(ngModel)]="filteredOccupationInput"/>
</div>
<div *ngIf="filteredOccupations && filteredOccupationInput.length > 1">
<p *ngFor="let filteredOccupation of filteredOccupations">
{{ filteredOccupation.occupationText }}
</p>
</div>
Это на самом деле все еще работает, за исключением того, что я получаю предупреждение от Angular Forms в консоли: " Похоже, вы используете ngModel в том же поле формы, что и formControlName. Поддержка использования свойства ввода ngModel и события ngModelChange Директивы с реактивной формой устарели в Angular v6 и будут удалены в Angular v7."
Я использую Angular v7 - точнее v7.1.1 - и поэтому я удивлен, что код все еще работает. Однако, если я добавлю второй элемент управления в свой HTML с другим именем, привязками, объектом привязки и т. Д., Произойдет странная вещь (например, я набираю символы в первом элементе управления, и они также появляются во втором элементе управления, даже если его имя и привязки совершенно разные) ,
Так что я не могу проигнорировать это предупреждение, и мне нужно избавиться от этой надоедливой [(ngModel)] привязки во входном текстовом поле.
Если я уберу его, мой фильтр сломается полностью. Поэтому я добавил вызов onChanges для поля ввода в компоненте (вызывая его из ngOnInit), чтобы он создавал подписку для любых изменений ввода, например ...
private onFormChanges(): void {
this.employmentDetailsForm.get('filteredOccupationInput').valueChanges.subscribe(value => {
console.log(this.debugId + '.onFormChanges(filteredOccupationInit). New value is ' + value);
this.performFilterOccupation(value);
});
}
В журнале консоли я вижу, что изменения фильтра записываются при вводе нового текста и вызывается executeFilterOccupation с этим новым значением, НО изменения, которые он вносит в FilterOccupations не отражаются в пользовательском интерфейсе, если только я не добавлю, что pesky "не использует" привязку ngModel обратно в микс.
Что мне нужно сделать, чтобы убедиться, что измененное содержимое filterOccupations отображается в пользовательском интерфейсе, когда у меня нет привязки ngModel?