Как преобразовать отфильтрованное текстовое поле автозаполнения из угловой шаблонной формы в угловую реактивную форму без ngModel - PullRequest
0 голосов
/ 08 января 2019

Я пытаюсь преобразовать текстовое поле ввода, которое имитирует выпадающий список с автозаполнением. Когда пользователь введет в текстовое поле хотя бы два символа, я хочу отобразить отфильтрованный список объектов, которые начинаются с введенных символов.

Используя шаблонные формы, я имел это в виду:

    
          <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?

...