Angular 6 Проверка автозаполнения материала

Мы разрабатываем наше приложение, используя материал Angular 6. У нас есть поле выбора, которое имеет функцию автозаполнения. У меня есть обязательная проверка для моего поля выбора, поэтому, когда пользователь ищет опцию, и он / она не выбирает ни одну из опций, но сохраняет условие поиска в поле выбора, и поскольку требуется только проверка поля выбора, моя форма публикуется API. Чего я хочу добиться, так это не разрешить пользователю публиковать форму, если он / она не выберет один из вариантов, а не просто указание поискового запроса. Как мне этого добиться?

<mat-form-field>
   <input matInput placeholder="Pick one" aria-label="pick one" [matAutocomplete]="auto" [formControl]="form.controls['SELECTBOX_VALUE']">
      <mat-autocomplete #auto="matAutocomplete">
           <mat-option *ngFor="let option of myOptions | async" [value]="option.name"> <span>{{ option.name }}</span> </mat-option>
            </mat-autocomplete>
</mat-form-field>
<small *ngIf="!form.controls['SELECTBOX_VALUE'].valid && form.controls['SELECTBOX_DEGER'].touched" class="mat-text-warn">Please select.</small>

ngOnInit() {
    this.form = this.fb.group({
        ... some other fields
        SELECTBOX_VALUE: [null, Validators.required]
    });

Вот мой код фильтра для автокомпиляции это довольно прямо

this.form.get('SELECTBOX_VALUE').valueChanges
        .pipe(
            startWith(''),
            map(option => secenek ? this.doFilter(option) : this.options.slice())
        );

doFilter (name: string) {
    return this.myOptions.filter(option =>
        option.name.toLowerCase().indexOf(name.toLowerCase()) === 0);
}

4 ответа

Решение

Для тех, кому может понадобиться подобный подход. Вот мое решение. Я создал собственное правило проверки в соответствии с моими потребностями.

SELECTBOX_VALUE: [null, Validators.compose(
  [Validators.required, FormCustomValidators.valueSelected(this.myArray)]
)]

export class FormCustomValidators {
  static valueSelected(myArray: any[]): ValidatorFn {

    return (c: AbstractControl): { [key: string]: boolean } | null => {
      let selectboxValue = c.value;
      let pickedOrNot = myArray.filter(alias => alias.name === selectboxValue);

      if (pickedOrNot.length > 0) {
        // everything's fine. return no error. therefore it's null.
        return null;

      } else {
        //there's no matching selectboxvalue selected. so return match error.
        return { 'match': true };
      }
    }
  }
}

Есть два сценария с автозаполнением Angular Material, которые, возможно, потребуется проверить по списку выбранных опций:

  1. Массив строк - предлагаемые параметры определены в массиве строк.
  2. Массив объектов - предлагаемые параметры - это свойство объекта, определенное для массива объектов (в этом сценарииdisplayWith Будет использован ввод.)

** Демо Stackblitz **

Проверить параметры из массива строк

Чтобы проверить autocomplete для массива параметров строки валидатор может принять массив параметров и проверить, включено ли контрольное значение.

function autocompleteStringValidator(validOptions: Array<string>): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    if (validOptions.indexOf(control.value) !== -1) {
      return null  /* valid option selected */
    }
    return { 'invalidAutocompleteString': { value: control.value } }
  }
}

Валидатор можно добавить в FormControl наряду с другими встроенными валидаторами, такими как Validators.required:

public autocompleteControl = new FormControl('', 
      { validators: [autocompleteStringValidator(this.options), Validators.required] })

Проверить параметры из массива объектов

Чтобы проверить autocomplete против массива параметров объекта, валидатор может использовать тот факт, что control.value будет только string если действительный Object вариант не выбран.

function autocompleteObjectValidator(): ValidatorFn {
  return (control: AbstractControl): { [key: string]: any } | null => {
    if (typeof control.value === 'string') {
      return { 'invalidAutocompleteObject': { value: control.value } }
    }
    return null  /* valid option selected */
  }
}

Вот решение, которое проверяет выбранный параметр на массив, полученный из наблюдаемого.

      export class FormCustomValidators {
  static valueSelected<T>(exists: (value: T) => boolean): ValidatorFn {

    return (c: AbstractControl): { [key: string]: boolean } | null => {
      let selectboxValue = c.value;

      if (exists(selectboxValue)) {
        // everything's fine. return no error. therefore it's null.
        return null;
      } else {
        //there's no matching selectboxvalue selected. so return match error.
        return { 'match': true };
      }
    }
  }
}

export class MyComponent implements OnInit {

  myObjects: MyObject[] = [];

  ngOnInit(): void {
    this.formControl = new FormControl('', Validators.compose([Validators.required, FormCustomValidators.valueSelected<MyObject>(this.myObjectExists.bind(this))]));
    this.service.getMyObjects().subscribe((myObjects) => {
      this.myObjects = myObjects
    }
  }
  
  private myObjectExists(value): boolean {
    return this.myObjects.some(v => v === value);
  }

Вы можете добавить в свою функцию отправки проверку правильности для полей,

Submit() {
 if(this.form.valid) {
   // send to API
 } else {
   // show error
 }
}
Другие вопросы по тегам