BACK
Lessons32. UI filters with startWith and combineLatest
Lessons · 32

32. UI filters with startWith and combineLatest

Practice: list filters

This lesson brings two earlier concepts together: combineLatest to assemble state and startWith for each filter's starting value.

Why startWith on each source

Remember the combineLatest trap: until every source has emitted at least once, nothing comes out. If the filters are created lazily (from input events, say), the user might not touch a field for a while. So each source is given a "default" via startWith.

What happens, step by step

  1. At 0ms both startWiths emit immediately → output Filter: /all.
  2. At 20ms query$ changes to 'rxjs' → output Filter: rxjs/all.
  3. At 40ms status$ changes to 'active' → output Filter: rxjs/active.

Your task

  1. On query$, add startWith('') in the pipe (after map, comma-separated).
  2. On status$, add startWith('all').
  3. The combineLatest + map logic is already done — no need to change it.

Deterministic check

This task's check runs in TestScheduler virtual time. If your solution is right, the console shows only Test Passed!. Don't add extra console.logs, or the check will fail.

Solution spoiler · click to reveal
const { timer, combineLatest, map, startWith } = Rx;

const query$ = timer(20).pipe(
  map(() => 'rxjs'),
  startWith('')
);

const status$ = timer(40).pipe(
  map(() => 'active'),
  startWith('all')
);

const filters$ = combineLatest([query$, status$]).pipe(
  map(([query, status]) => 'Filter: ' + query + '/' + status)
);
script.ts // TypeScript
CONSOLE · Console output
Hit Run to see the result...