I subscribe to filter1
, filter2
, and filter3
, all of which are FormControl
instances. Whenever at least one of them changes, I want to retrieve the values of all three. Initially, I attempted to use combineLatest
, but I noticed that it emits only when all of them have emitted values. Then, I tried using merge
, but encountered an issue where it only returned the field that changed.
So, how can I obtain an object { filter1, filter2, filter3 }
using RxJS?
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { merge } from 'rxjs';
import { map } from 'rxjs/operators';
console.clear();
@Component({
selector: 'app-root',
standalone: true,
imports: [FormsModule, ReactiveFormsModule, CommonModule],
template: `
<input [formControl]="filter1">
<input [formControl]="filter2">
<input [formControl]="filter3">
`,
})
export class App {
name = 'Angular';
filter1 = new FormControl();
filter2 = new FormControl();
filter3 = new FormControl();
constructor() {
merge(
this.filter1.valueChanges.pipe(map(value => ({ filter1: value }))),
this.filter2.valueChanges.pipe(map(value => ({ filter2: value }))),
this.filter3.valueChanges.pipe(map(value => ({ filter3: value })))
).subscribe((x) => {
console.log(x);
});
}
}
bootstrapApplication(App);
Please note that I don't want to use formGroup
and I want to know how to do it without use formGroup
.
The operator combineLatest
is the correct approach, but you need to use the startWith
operator for each observable first to provide an initial value. If you don't want the initial value with all filters empty, you can also pipe the result of combineLatest
through skip(1)
.
import { Component } from '@angular/core';
import { ReactiveFormsModule, FormControl } from '@angular/forms';
import { bootstrapApplication } from '@angular/platform-browser';
import { startWith, combineLatest } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
imports: [ReactiveFormsModule],
template: `
<input [formControl]="filter1" />
<input [formControl]="filter2" />
<input [formControl]="filter3" />
`,
})
export class AppComponent {
filter1 = new FormControl();
filter2 = new FormControl();
filter3 = new FormControl();
constructor() {
combineLatest({
filter1: this.filter1.valueChanges.pipe(startWith('')),
filter2: this.filter2.valueChanges.pipe(startWith('')),
filter3: this.filter3.valueChanges.pipe(startWith('')),
}).subscribe((x) => {
console.log(x);
});
}
}
bootstrapApplication(AppComponent);