Home > Software design >  2 way filtering with AngularMaterial autocomplete form control
2 way filtering with AngularMaterial autocomplete form control

Time:12-07

I want to create an Angular Material Autocomplete form control with two ways to filter the selectable options:

  1. The default way, when the user types in the text input, and only the options mathcing the search term will be visible, like in the examples on the Angular Material website.
  2. Above the autocomplete component there's a category select form control. When a category is chosen, I want to display only the elements in the chosen category, and allow the user to only search in these elements with the autocomplete text input.

Here is my code in the component class:

category = new FormControl('');
product = new FormControl('');
inwardForm = new FormGroup({
  category: this.category,
  product: this.product,
});


ngOnInit(): void {
    combineLatest([
      this.inwardForm.get('product')!.valueChanges,
      this.inwardForm.get('category')!.valueChanges,
    ]).pipe(
      startWith(['', undefined])
    ).subscribe(result=>{
      console.log(result);
    });
  }

My problem is that, after initializing the component, when I start typing in the autocomplete component, nothing happens. After chosing a category in the category select component, the console.log fires. After a category is chosen, and then typing to the autocomplete the console.log fires again at each keystroke.

So after a category is chosen, it works as expected, but I dont want the category select to be obligatory. What could be the problem?

CodePudding user response:

Actually it doesn't matter which one you first touch. combineLatest fires only after the observables defined inside emits at least once. Currently neither is emitting from the beginning, so you need to interact with both of them to see the console log. I see you are trying to fire it up using startWith, but the startWith needs to be on the formcontrols instead of the combineLatest:

ngOnInit(): void {
  combineLatest([
    this.inwardForm.get('product')!.valueChanges.pipe(startWith('')),
    this.inwardForm.get('category')!.valueChanges.pipe(startWith('')),
  ])
  .subscribe((result) => {
    console.log(result);
  });
}

Though you could also just listen to the parent form, then would be no need for combineLatest:

this.inwardForm.valueChanges.subscribe(values => {
   console.log(values.product, values.category);
})

Remember to unsubscribe!

  • Related