Observable Value

Learn how to use Observable values (like `BehaviorSubject` or `Observable`) in form inputs.

Overview

The value property in FormInput supports Observable values, which allows you to:

  1. Create reactive form fields - Form inputs that automatically update when Observable emits new values

  2. Enable cross-field dependencies - Update one field based on changes in another field using onChange callbacks

  3. Use BehaviorSubject for state management - Manage form field values reactively using RxJS BehaviorSubject

  4. Support dynamic value updates - Update form values programmatically without direct form manipulation


Use Case 1: Reactive Field with BehaviorSubject

Scenario

You have a form with two related fields:

  • Name field: User enters a project name

  • Slug field: Automatically generates a URL-friendly slug from the name (lowercase, spaces replaced)

You want the slug field to update automatically whenever the name changes.

Configuration

import { BehaviorSubject } from 'rxjs';
import { FormInput, FormInputType } from '@tradinos/cms-frontend-form';

export class ProjectService extends EntityService<Project> {
  // Create a BehaviorSubject to hold the slug value
  public slugText$ = new BehaviorSubject<string>('');

  override manualInputsFn = (project?: Project) => {
    return [
      {
        key: 'name',
        inputType: FormInputType.text,
        value: project?.name,
        onChange: (value: string) => {
          // Update the slug Observable when name changes
          this.slugText$.next(value.toLowerCase());
        }
      },
      {
        key: 'slug',
        inputType: FormInputType.text,
        value: this.slugText$,  // Use Observable as value
      },
    ] as FormInput<Project>[];
  }
}

Example from Codebase

File: src/app/dashboard/project/services/project.service.ts

Parameters Explained

Parameter
Type
Description
Required

value

Observable<T> | BehaviorSubject<T> | T

Can be a static value, Observable, or BehaviorSubject

Optional

onChange

(value: T) => void

Callback function called when the field value changes

Optional

How it Works

  1. BehaviorSubject Creation: Create a BehaviorSubject to hold the reactive value

  2. onChange Callback: Use onChange to update the Observable when the source field changes

  3. Observable Value: Pass the Observable as the value property

  4. Automatic Updates: The form library subscribes to the Observable and updates the field automatically when new values are emitted


Use Case 2: Initializing Observable with Existing Value

Scenario

When editing an existing entity, you want to initialize the Observable with the existing value from the database.

Configuration

How it Works

  1. Check for Existing Value: Before returning the form inputs, check if there's an existing value

  2. Initialize Observable: Use next() to set the initial value in the BehaviorSubject

  3. Form Updates: The form will display the initialized value and continue to react to changes


Use Case 3: Multiple Dependent Fields

Scenario

You have multiple fields that depend on a single source field, all updating reactively.

Configuration


Complete Examples

Example 1: Auto-Generated Slug from Name

Result:

  • User types "My Awesome Project" in the name field

  • Slug field automatically updates to "my-awesome-project."

  • Both fields are reactive and stay in sync


Example 2: Calculated Field


Example 3: Conditional Field Updates


Comparison Table

Value Type
Use Case
Example
Reactive

Static value

Simple form fields

value: project?.name

❌ No

BehaviorSubject

Reactive fields with initial value

value: this.slugText$

✅ Yes

Observable

Reactive fields from async sources

value: this.data$

✅ Yes


Best Practices

  1. Use BehaviorSubject for form values: BehaviorSubject is ideal because it has an initial value and can be updated synchronously

  2. Initialize with existing values: When editing, initialize the Observable with the existing value

  3. Clean up subscriptions: The form library handles subscription cleanup automatically, but be aware of memory leaks if you manually subscribe

  4. Use onChange for dependencies: Use onChange callbacks to update dependent Observable fields

  5. Handle null/undefined: Always check for null/undefined values before initializing Observables

  6. Type safety: Use TypeScript generics for better type safety


Common Patterns

Pattern 1: Auto-Generated Slug

Pattern 2: Calculated Totals

Pattern 3: Conditional Formatting


  • App configuration - Learn about CMS_FORM_CONFIG options

  • Form Input Types - See available form input types

  • onChange Callbacks - Understand onChange behavior


Summary

The value property in FormInput supports Observable values, enabling reactive form behavior:

  • BehaviorSubject: Ideal for reactive form fields with initial values

  • onChange integration: Update Observables when source fields change

  • Automatic updates: Form fields automatically update when Observable emits

  • Cross-field dependencies: Create relationships between form fields

  • Dynamic values: Update form values programmatically through Observables

This feature enables powerful reactive form patterns, making it easy to create dynamic, interdependent form fields that update automatically based on user input or programmatic changes.

Last updated