0

I need your help. I'm working with reactive forms and using matautocomplete to search for elements. I subscribe to changes in my input to search for my items. The fact is that I need to insert a certain value into my input using patchValue. I try to do it in several ways, but it doesn't work. What am I doing wrong? Thank you very much

HTML

<input [matAutocomplete]="auto" matInput
       formControlName="targetListValue"
       (input)="inputFilterValue()">
<mat-autocomplete
   #auto="matAutocomplete"
   [displayWith]="displayFn"
   <mat-option *ngFor="let targetItem of filteredTargetListOptions"
               [value]="targetItem">
       {{targetItem.name}}
   </mat-option>
</mat-autocomplete>

TS

ngOnInit(): void {
   this.form = new FormGroup({
     targetListValue: new FormControl(null, [Validators.required]),
   });

inputFilterValue() {
   this.form.controls.targetListValue.valueChanges.subscribe((inputValue) => {
      this.filteredTargetListOptions = this.filteredTargetListOptions.filter(element => element.name.toLowerCase().includes(inputValue) || element.name.includes(inputValue));
})
}

displayFn(option?: ITargetData): string | undefined {
   return option ? option.name : undefined;
}

// First way
setTimeout(() => {
   this.form.patchValue({ targetListValue: 'Hello' })
},0)

// Second way
this.form.controls.targetListValue.patchValue('Hello');
Dmitry Chernyak
  • 295
  • 3
  • 12
  • **not** call to the function inputFilterValue in `(input)` event. You only need subscribe to valueChanges **after** create the form. Also you only can use patchValue **after** create the form.BTW you need **two** arrays, allTargetListOptions and filteredTargetListOptions, so `this.filteredTargetListOptions = this.allTargetListOptions.filter(element => ...)` else you're filtered over a filtered over a filtered – Eliseo Jul 12 '22 at 17:34
  • @Eliseo thank you, but it question about mat autocomplete – Dmitry Chernyak Jul 12 '22 at 18:05
  • 1
    your code is wrong, you can **not** call to the function inputFilterValue in event (input), you can not use this.filteredTargetListOptions = this.filteredTargetListOptions.filter(...) because you loose the array filteredTargetListOption. In the example of the docs use the pipe async to show the options and this is the reason only need a unique array. Sure I don't answer your question about pathcValue, but the code you show to create a mat-auto-complete can **not** work – Eliseo Jul 12 '22 at 18:45

1 Answers1

0

Form Creation - Set the Form in the component constructor() {}, not within ngOnInit(). That way its ready to go when ngOnInit() runs and you know you're not running into any issues that would require setTimeout or other solutions like other component lifecycle hooks.

Also - along with that, is there a reason you're not setting it by default? IE -

  constructor() {
    this.form = new FormGroup({
      targetListValue: new FormControl( 'Hello', [Validators.required]),
    });
  }

Patching - To patch the value after, I would use the .get() function, which would be

  ngOnInit(): void {
    this.form.get("targetListValue").patchValue('Hello') 
  }

Form Changes - You're subscribing to the event, but you could do this using event binding on the form element itself. I typically use (blur) which will update it once you leave the field, but there are many more if you want to do it on every keydown, etc.

<input type="text" placeholder="Search..." formControlName="targetListValue" (blur)="updateFilteredTargetListOptions()">

then define that function that will run in the .ts. No need to subscribe (which can lead to memory leaks, etc if you dont properly unsubscribe or handle that)

updateFilteredTargetListOptions() {
    this.filteredTargetListOptions = this.filteredTargetListOptions.filter(element => element.name.toLowerCase().includes(inputValue) || element.name.includes(inputValue));
}
  • Thanks for the reply and thanks for the suggested solution, but it doesn't apply to my question. How exactly to specify the patchValue for mat autocomplete, because it all doesn't work for me. Thank you) – Dmitry Chernyak Jul 12 '22 at 17:15
  • I think the issue may be caused by you building to form late (onInit) and also not calling the function with the event binder on the input. I'd start with what I have above, or similar, then narrow it down – J.C. Gilmore Jul 13 '22 at 15:59