如何在Angular中不使用FormGroup通过RxJS获取多FormControl值
问题:如何通过RxJS获取多个FormControl的完整值(不使用FormGroup)
我有三个FormControl实例filter1、filter2、filter3,希望当其中至少一个值发生变化时,获取这三个控件的全部值。尝试过combineLatest,但它仅在所有控件都发出值时才触发;用merge的话,只能返回发生变化的字段。请问如何通过RxJS获取包含三个控件值的{ filter1, filter2, filter3 }对象?注:不想使用FormGroup。
解决方案
有两种简洁的实现方式,都不需要依赖FormGroup:
方法1:merge + 直接读取控件当前值
利用merge监听所有控件的valueChanges,每次触发时直接读取三个控件的当前值,组合成目标对象:
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, this.filter2.valueChanges, this.filter3.valueChanges ).pipe( map(() => ({ filter1: this.filter1.value, filter2: this.filter2.value, filter3: this.filter3.value, })) ).subscribe((filters) => { console.log(filters); }); } } bootstrapApplication(App);
方法2:combineLatest + startWith
给每个valueChanges流加上startWith,传入控件的初始值,这样combineLatest会在页面加载时就触发一次,之后任意控件值变化也会同步返回完整的对象:
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 { combineLatest } from 'rxjs'; import { startWith } 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() { combineLatest([ this.filter1.valueChanges.pipe(startWith(this.filter1.value)), this.filter2.valueChanges.pipe(startWith(this.filter2.value)), this.filter3.valueChanges.pipe(startWith(this.filter3.value)), ]).pipe( map(([f1, f2, f3]) => ({ filter1: f1, filter2: f2, filter3: f3, })) ).subscribe((filters) => { console.log(filters); }); } } bootstrapApplication(App);
说明
- 方法1逻辑简单直接,每次变化时主动读取控件当前值,无需额外处理初始状态;
- 方法2更贴合RxJS的流式思维,通过
startWith补全初始值,让combineLatest的行为符合需求,适合需要严格遵循响应式数据流的场景。
内容的提问来源于stack exchange,提问作者amirc
相关产品推荐
相关产品推荐

