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