Angular Material: How to validate Autocomplete against suggested options?

There are two scenarios with Angular Material Autocomplete that may need to be validated against a list of selected options:

  1. Array of strings - Suggested options are defined in an array of strings
  2. Array of Objects - Suggested options are an object property defined on an array of Objects (In this scenario, displayWith Input would be used.)

** Stackblitz Demo **

Validate Options from Array of strings

To validate autocomplete against an array of string options, the validator may accept the array of options and check if the control value is included.

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

The validator could be added to a FormControl along with other built-in validators such as Validators.required:

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

Validate Options from Array of Objects

To validate autocomplete against an array of object options, the validator can leverage the fact that the control.value will only be a string if a valid Object option has not been selected.

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 */
  }
}

For those who may need a similar approach. Here's my solution. I've built a custom validation rule according to my needs.

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 };
      }
    };
  }
}