angularangular-materialautocomplete

Angular 17 Material mat-autocomplete mat-input within a FormGroup


Based on the following example on the Angular Material Site for v17 https://v17.material.angular.io/components/autocomplete/overview#automatically-highlighting-the-first-option, I am trying to setup this but leveraging an Input FormControl within a FormGroup. However in doing so, I am finding that the FormControl valueChanges observable is not firing.

I did some testing to make sure the that if I use the FormControl within a FormGroup with wiring it up to the UI, I can see the Observable firing.

example markup that works

          <mat-form-field class="contact-full-width">
            <mat-label>country</mat-label>
            <input
              placeholder="Pick one"
              aria-label="Number"
              matInput
              formControlName="country"
              required>
           
          </mat-form-field>

example component code that works

  public registerForm = new FormGroup({
    email: new FormControl(''),
    firstName: new FormControl(''),
    lastName: new FormControl(''),
    addressLine1: new FormControl(''),
    addressLine2: new FormControl(''),
    stateProvinceTerritory: new FormControl(''),
    cityTownSuburb: new FormControl(''),
    country: new FormControl(''),
    postalCode: new FormControl(''),
  });

private _filteredCountries: Array<Country> = [];

public get filteredCountries () {
    return this._filteredCountries;
  }


this._subCountryInputChange = this.registerForm.get('country')?.valueChanges.pipe(
        startWith(''),
        filter((value) => (!value ? 0 : value.length) > 2),
        debounceTime(500),
        map((data: any)  => {
          const name = typeof data === 'string' ? data : data?.name;
          return data ? this.filterList<Country>(data, this._masterCountries) : this._masterCountries.slice();
        })
      ).subscribe({
         next:(data: Array<Country>) => { this._filteredCountries = data; },
         error:(e: any) => { console.log(e) }, 
         complete:() => { console.log('ok') }
      })

If I place a break point on the line with next I can see the assignment to this._filteredCountries occurring.

However, if I change the markup to wireup the filteredCountries to the auto-complete, nothing happens.

example markup

<mat-form-field class="contact-full-width">
            <mat-label>country</mat-label>
            <input
              placeholder="Pick one"
              aria-label="Number"
              matInput
              formControlName="country"
              [matAutocomplete]="auto"
              required>
            <mat-autocomplete name="country" #auto="matAutocomplete" [displayWith]="displayFn" requireSelection>
             <!-- @for (option of filteredOptions | async; track option) {-->
              @for (option of filteredCountries; track option) {
                <mat-option [value]="option">{{option.name}}</mat-option>
              }
            </mat-autocomplete>
          </mat-form-field>

I have also tried the observable / async approach wiring the observable directly to the control in markup but that does not work either.

Edit: After more experimentation, I setup the FormControl outside of the FormGroup to see if this makes a difference. It did not.

I am not sure what I am missing but any assistance would be appreciated


Solution

  • After a lot of digging into this code and experimenting with different changes, it appears it is developer error. I had the .TS snippets in the constructor. It looks like these observables need to be in ngInit(). This was an oversight.