16 Dec 2025
4 min

Building Dynamic Forms in Angular Using JSON Schema and Signals

In modern applications, forms are everywhere registration flows, onboarding steps, product configurations, surveys, admin panels, and more. But hardcoding each form manually quickly becomes unsustainable, especially when requirements change frequently. What if the UI could adapt automatically to configurations without modifying the Angular component each time?

This is where JSON-driven dynamic forms shine.

Instead of writing form controls manually, Define the structure in a JSON file or fetch it from an API. Angular then renders the UI dynamically based on that configuration. And with the introduction of Angular Signals, this pattern becomes even more powerful, more reactive, more predictable, and significantly cleaner.

In this blog, we explore how to architect a fully dynamic form system using JSON Schema and Angular Signals, without diving into implementation code. 

Why Build Forms Using JSON Schema?

Hardcoded forms create several challenges:

  • Every new field requires UI and TS changes.
  • Validations must be written repeatedly.
  • Different user roles or scenarios may need different versions of the same form.
  • Business teams often modify requirements faster than developers can update code.

By using JSON Schema:

  • The form structure lives outside the codebase.
  • The UI becomes configuration-driven, not code-driven.
  • Updates are instant modify JSON, refresh view.
  • The same component can render multiple forms dynamically.

This pattern is used in enterprise workflow engines, onboarding systems, HR systems, survey platforms, CMS-driven UIs, and no-code form builders.

How the Architecture Works (Conceptually)

A dynamic form system has five key building blocks:

Here is a demo JSON file: 

{
  "title": "User Registration",
  "fields": [
    {
      "type": "text",
      "label": "First Name*",
      "name": "firstName",
      "validations": { "required": true, "minLength": 3 }
    },
    {
      "type": "text",
      "label": "Last Name*",
      "name": "lastName",
      "validations": { "required": true }
    },
    {
      "type": "email",
      "label": "Email",
      "name": "email",
      "validations": { "required": false }
    },
    {
      "type": "select",
      "label": "Country*",
      "name": "country",
      "options": ["Bangladesh", "Poland", "Turkey"],
      "validations": { "required": true }
    },
    {
      "type": "checkbox",
      "label": "Accept Terms*",
      "name": "terms",
      "validations": { "requiredTrue": true }
    }
  ]
}

1. The JSON Schema

This is a simple JSON file or API response that describes:

  • Title of the form
  • List of fields
  • Field types (text, email, select, checkbox, etc.)
  • Validation rules (required, minLength, requiredTrue)
  • Dropdown choices for select fields

Backend or CMS can update this anytime without touching Angular code.

2. Dynamic Form Service

This service loads the schema either from assets or an API.
Its job is to:

  • Fetch the form metadata.
  • Prepare initial values.
  • Pass the schema to the component.

This isolates the fetching logic and keeps the component clean.

3. Signals for Form State

Signals provide a highly reactive way to manage UI state. They replace manual subscriptions and simplify change detection.

A signals-based dynamic form typically maintains:

  • fields: the list of field definitions
  • title: the form heading
  • values: a record of current user inputs
  • touched: tracks which fields the user interacted with
  • errors (computed): automatically recalculated validation messages
  • isValid (computed): determines if the form can be submitted

Every time a value changes, signals propagate updates instantly to the UI without explicit subscriptions.

4. Dynamic Rendering in the Template

The template doesn’t contain any hardcoded form fields.

Instead, it loops over the schema and renders:

  • Text or email inputs
  • Select dropdowns
  • Checkboxes
  • Validation messages

The correct UI element appears automatically depending on the field type.
Add a new field in the JSON? It appears instantly in the UI.

This is the core of configuration-based rendering.

5. Submission Flow

When the form is valid and submitted:

  • Collect the state stored in the signals.
  • Process it such as sending it to an API.

Since the form is schema-driven, the submission logic is the only part that stays static.

Why Angular Signals Make This Better

Before Signals, dynamic forms usually required reactive forms with lots of control creation, subscriptions, and boilerplate. Signals reduce this dramatically.

Key advantages include:

  • Automatic recomputation of derived values (errors, validation states).
  • No manual unsubscribe or subscription management.
  • A more predictable, state-driven architecture.
  • Simpler mental model: “state in, UI out.”

Signals align perfectly with the idea of form-as-state.

Data Flow: How Everything Connects

  1. Angular loads the JSON schema.
  2. Service maps it into fields, initial values, and touched state.
  3. Signals store form-related state reactively.
  4. Template renders UI based on schema fields.
  5. When a user interacts, signals update instantly.
  6. Computed validations re-evaluate.
  7. The submit button becomes active once all validations pass.
  8. Final values are submitted or logged.

This gives a clean, maintainable, and scalable workflow.

Real-World Use Cases

This design is used in scenarios such as:

  • Form builders for no-code platforms.
  • HR onboarding systems where questions vary by role.
  • Admin dashboards where fields frequently change.
  • Multi-step wizards.
  • Dynamic CMS-driven landing pages.
  • Configuration UIs in SaaS applications.

Instead of changing Angular code each time, simply ship new JSON.

When Should We Use This Approach?

This pattern is most valuable when:

  • Form fields change frequently.
  • Multiple forms share the same rendering logic.
  • Want to empower non-developers to update UI via JSON.
  • For a clean and maintainable Angular architecture.
  • Building a reusable form engine.

If the forms rarely change, manual forms may still be simpler. But for dynamic, data-driven UIs, JSON + Signals is a perfect fit.

Final Thoughts

Dynamic forms powered by JSON Schema and Angular Signals combine two powerful ideas:

  • Configuration-driven UI
  • Reactive state management

Together, they enable us to build flexible, maintainable, and scalable form systems that adapt to business needs instantly.

This approach eliminates repetitive form code, reduces UI maintenance overhead, and empowers to create forms that evolve without redeployment.


Stackblitz Link:

https://stackblitz.com/edit/dynamic-form-angularv019?file=src%2Fmain.ts

Frequently asked questions

How do I build a dynamic form in Angular from a JSON schema?

Define the form structure in a JSON file or API response that lists the form title and an array of fields, each with a type, label, name, and optional validations. A dynamic form service loads this schema and prepares initial values, while the template loops over the fields and renders the matching input for each type. Adding or changing a field then only requires updating the JSON, not the Angular component.

Why use Angular signals instead of subscriptions to manage dynamic form state?

Signals store the form's fields, title, values, and touched state as reactive values, so the UI updates whenever a value changes without explicit subscriptions. Derived state such as errors and isValid is expressed as computed values that recalculate automatically. This removes the manual subscribe and unsubscribe boilerplate that dynamic reactive forms often required, giving a simpler model of state in, UI out.

Which validation rules can a JSON-driven Angular form support?

The example schema uses required, minLength, and requiredTrue rules inside each field's validations object, for example required for mandatory text inputs and requiredTrue for a terms checkbox. Select fields take an options array for their dropdown choices. Because rules live in JSON, one rendering engine can enforce different rules per form. Supporting additional rules means extending the logic that interprets the JSON.

How do I enable a submit button only when a dynamic Angular form is valid?

Use a computed signal such as isValid that re-evaluates validation across all fields, and bind the submit button's disabled state to it. The button becomes active only after every field's rules pass. On submit, the form collects the values held in its signals and passes them to your submission logic, such as an API call, which is the only part of the flow that stays static.

Should dynamic form schemas be loaded from local assets or an API in Angular?

Either works, because a dynamic form service can fetch the schema from a local assets JSON file or from an API response. Loading it from an API or CMS lets backend teams change the form without redeploying the Angular app. Keeping the fetching in a dedicated service isolates that logic and keeps the component clean, since the service also prepares initial values and passes the schema to the component.

Share this post

Sign up for our newsletter

Stay up-to-date with the trends and be a part of a thriving community.