Frontend Development 11 min read

Master Reactive Forms in Angular with RxJS: A Practical Example

This article explains why reactive programming simplifies logic, demonstrates a concrete age‑selection use case using RxJS operators like combineLatest and map, and shows how Angular's reactive forms, async pipe, and new ngIf features streamline UI development.

Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Tencent IMWeb Frontend Team
Master Reactive Forms in Angular with RxJS: A Practical Example

Why Use Reactive Programming?

Reactive programming lets you view every change as a data stream, making program logic clearer. For example, consider a UI that needs to input an age together with a unit (years, months, days) before a birthday field.

The requirements are:

Age can be expressed in years, months, or days.

If the age is ≤ 3 months, use days; if ≤ 2 years, use months; otherwise use years.

When the age changes, the birthday field should update accordingly, based on the selected unit.

Traditional code would require separate event handlers for the age and unit controls. With RxJS we treat each control as an Observable stream.

Rx defines three kinds of streams:

Never‑ending streams.

Finite streams that complete after a number of emissions.

Special streams that never emit (used for edge cases).

In our example we have two source streams: one for the age value and one for the unit. Each change produces a new value in its stream. We need a combined stream that emits whenever either source changes, always containing the latest value from both.

The RxJS operator that does exactly this is

combineLatest

. Using

age$

for the age stream and

ageUnit$

for the unit stream, the combined logic (simplified to use days as the unit) looks like:

After merging, we still need to convert the combined value (age in days) to an actual birthdate. The

map

operator together with

momentjs

can subtract the number of days from the current date to produce an estimated birthday.

RxJS in Reactive Forms

Angular offers two form models: template‑driven and reactive. The reactive approach uses a

FormGroup

with three simple steps:

Add

formControlName="..."

to each control in the template.

Bind the form element with

[formGroup]="myForm"

, where

myForm

is a

FormGroup

instance defined in the component.

In the component constructor inject

FormBuilder

and create the form controls, e.g.

this.myForm = this.fb.group({ age: [], ageUnit: [] })

.

To obtain the two source streams, we simply listen to the

valueChanges

of each control:

The

valueChanges

observable can be refined with common RxJS operators:

.debounceTime(500)

to ignore rapid keystrokes,

.distinctUntilChanged()

to suppress duplicate values, and

.startWith(initialValue)

to provide an initial emission.

Async Pipe

Normally you would manually subscribe to an Observable and unsubscribe in

ngOnDestroy

to avoid memory leaks. Angular’s

async

pipe automates this: it subscribes when the component is created and unsubscribes when it is destroyed.

By using the pipe in the template, e.g.

[value]="computed$ | async"

, the input’s value is bound to the latest emission of

computed$

without any explicit subscription code.

Angular 4 ngIf Improvements

Angular 4 adds an

else

clause to

ngIf

, allowing a single directive to handle both true and false cases with template references.

It also supports assigning the result of the condition to a local variable, reducing repetitive

(auth$|async)

expressions.

FrontendReactive ProgrammingRxJSAngularForms
Tencent IMWeb Frontend Team
Written by

Tencent IMWeb Frontend Team

IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.