npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kedevked/json-schema-form

v0.0.2

Published

Render a fully reactive, signal-based Angular form from a JSON Schema string.

Readme

@kedevked/json-schema-form

An Angular library that renders a fully reactive, signal-based form directly from a JSON Schema string. Built on top of Angular Signal Forms.

Features

  • Renders object, string, number, integer, boolean, and enum fields from a JSON Schema
  • Nested objects with recursive rendering
  • Built-in validation: required, minLength, maxLength, minimum, maximum, enum
  • Conditional fields via if/then/else and dependentRequired
  • Fully customizable field components for each field kind
  • No built-in submit button, so you keep full control over form shell and actions

Installation

npm install @kedevked/json-schema-form

Peer dependencies:

  • @angular/common ^22.0.0
  • @angular/core ^22.0.0
  • @angular/forms ^22.0.0

Quick start

import { Component } from '@angular/core';
import { JsonSchemaForm, type JsonSchemaFormModel } from '@kedevked/json-schema-form';

@Component({
	standalone: true,
	imports: [JsonSchemaForm],
	template: `
		<form (ngSubmit)="formRef.submit()">
			<json-schema-form #formRef [schema]="schema" (formSubmit)="onSubmit($event)" />
			<button type="submit">Submit</button>
		</form>
	`,
})
export class MyComponent {
	schema = JSON.stringify({
		type: 'object',
		required: ['name'],
		properties: {
			name: { type: 'string', title: 'Name' },
			age: { type: 'integer', title: 'Age', minimum: 0, maximum: 120 },
		},
	});

	onSubmit(value: JsonSchemaFormModel) {
		console.log(value);
	}
}

Component API

Inputs

| Input | Type | Description | |---|---|---| | schema (required) | string | JSON Schema document as a string. Changing it rebuilds the form from scratch. | | field | FieldTree<JsonSchemaFormModel> | Use when embedding into an externally owned Signal Form. | | fieldComponents | Partial<JsonSchemaFieldComponentRegistry> | Per-instance field renderer overrides. | | validators | Partial<JsonSchemaValidatorRegistry> | Per-instance validator overrides. |

Outputs

| Output | Type | Description | |---|---|---| | valueChange | OutputRef<JsonSchemaFormModel> | Emits current form value on every change. | | formSubmit | OutputRef<JsonSchemaFormModel> | Emits value when submit() is called and form is valid. |

Methods

  • submit(): validates and emits formSubmit only when valid.

Naming and app semantics

submit() is intentionally low-level and generic. In app code, wrap it with your own domain-specific naming (for example saveProfile(), publish(), continue()).

Use valueChange as the source of truth for the current model in your component.

import { Component, signal } from '@angular/core';
import { JsonSchemaForm, type JsonSchemaFormModel } from '@kedevked/json-schema-form';

@Component({
	standalone: true,
	imports: [JsonSchemaForm],
	template: `
		<json-schema-form
			#formRef
			[schema]="schema"
			(valueChange)="currentValue.set($event)"
			(formSubmit)="submitted.set($event)"
		/>
		<button type="button" (click)="saveProfile(formRef)">Save profile</button>
	`,
})
export class MyComponent {
	schema = '{"type":"object","properties":{"name":{"type":"string"}}}';
	currentValue = signal<JsonSchemaFormModel | null>(null);
	submitted = signal<JsonSchemaFormModel | null>(null);

	saveProfile(form: JsonSchemaForm): void {
		form.submit();
	}
}
## Headless usage (no renderer components)

If you only want schema parsing, default model creation, and Signal Forms validation
without using `<json-schema-form>`, use `createJsonSchemaFormState()`.

```ts
import { Component } from '@angular/core';
import { FormField } from '@angular/forms/signals';
import { createJsonSchemaFormState } from '@kedevked/json-schema-form';

@Component({
	standalone: true,
	imports: [FormField],
	template: `
		<form (ngSubmit)="submit()">
			<input type="text" [formField]="state.fields.name" />
			<label>
				<input type="checkbox" [formField]="state.fields.subscribed" />
				Subscribed
			</label>
			<button type="submit">Submit</button>
		</form>
	`,
})
export class HeadlessFormComponent {
	readonly state = createJsonSchemaFormState(
		JSON.stringify({
			type: 'object',
			required: ['name'],
			properties: {
				name: { type: 'string' },
				subscribed: { type: 'boolean' },
			},
		}),
	);

	submit(): void {
		if (this.state.fields().valid()) {
			console.log(this.state.fields().value());
		}
	}
}
```

This pattern gives you complete control over layout and interactions while reusing
the package's schema normalization, default-value model generation, and validators.

If you call `createJsonSchemaFormState()` outside an Angular injection context,
pass `{ injector }` explicitly.

Supported JSON Schema keywords

| Keyword | Applies to | Effect | |---|---|---| | type | all | Selects field component type | | title | all | Field label | | description | all | Available in field view model | | required | object | Marks listed properties as required | | default | all | Initial value | | enum | string, number | Restricts values to allowed options | | minLength / maxLength | string | String length validation | | minimum / maximum | number, integer | Numeric range validation | | properties | object | Nested object field definitions | | if / then / else | object | Conditional required fields | | dependentRequired | object | Field dependencies |

Customizing field components

Register globally:

import { provideJsonSchemaFieldComponents } from '@kedevked/json-schema-form';
import { MyStringField, MyNumberField } from './my-fields';

export const appConfig = {
	providers: [
		provideJsonSchemaFieldComponents({
			string: MyStringField,
			number: MyNumberField,
		}),
	],
};

Or override per instance:

<json-schema-form [schema]="schema" [fieldComponents]="myComponents" />

Development

pnpm install
npx nx test json-schema-form
npx nx build json-schema-form

License

MIT