HTML- I'm trying to use Mat-autocomplete but its not working on very first time when component gets loaded i.e in ngOnInit(), Its saying cannot read properties of null (reading 'map')
<mat-form-field appearance="outline">
<input type="text" placeholder="Pick one" aria-label="Number" matInput [formControl]="myControl" [(ngModel)]="element.NEW_AMENITY_NAME" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" (optionSelected)='onSelect($event.option, i)'>
<mat-option *ngFor="let item of filteredOptions | async" [value]="item">
{{item}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
TS file -
ngOnInit(): void {
this.infoService.AmenityList.subscribe((res)=>{
this.AmenityList = res;
this.assignForm.push(this.createForm(1))
this.dataSource = [...this.assignForm.controls];
console.log(this.dataSource.END_TIME , "data");
})
this.displayName = this.AmenityList.map(a=>a.DISPLAY_NAME);
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value || '')),
);
}
its not working on very first time when we are laoding the component, attached image of error-
CodePudding user response:
Sync/Async issue.
I suggest you learn what is asynchronicity in JS before going further.
But quick solution.
private _data$ = this.infoService.AmenityList.pipe(shareReplay(1));
public names$ = this._data$.pipe(
map(list => list.map(item => item.name))
);
ngOnInit(): void {
this._data$.pipe(first()).subscribe((res)=>{
this.assignForm.push(this.createForm(1))
this.dataSource = [...this.assignForm.controls];
console.log(this.dataSource.END_TIME , "data");
})
this.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value || '')),
);
}
CodePudding user response:
this.AmenityList
is not set yet so its null, understand response only comes inside subscribe, anything outside runs before the result comes.
ngOnInit(): void {
this.infoService.AmenityList.subscribe((res)=>{
// runs after response comes
this.AmenityList = res;
this.assignForm.push(this.createForm(1))
this.dataSource = [...this.assignForm.controls];
console.log(this.dataSource.END_TIME , "data");
// }) you ended it here so the below code runs before the response comes
this.displayName = this.AmenityList.map(a=>a.DISPLAY_NAME);
}); // move it here, any code that depends on the response should be called after response
data.filteredOptions = this.myControl.valueChanges.pipe(
startWith(''),
map(value => this._filter(value || '')),
);
}