{"id":29790783,"url":"https://github.com/dashjoin/json-schema-form","last_synced_at":"2026-02-25T23:33:36.476Z","repository":{"id":40248100,"uuid":"245471501","full_name":"dashjoin/json-schema-form","owner":"dashjoin","description":"Angular JSON Schema Form Library","archived":false,"fork":false,"pushed_at":"2024-08-12T07:19:15.000Z","size":2081,"stargazers_count":88,"open_issues_count":30,"forks_count":26,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-15T16:38:55.182Z","etag":null,"topics":["angular","angular2","autocomplete","declarative-html-form","declarative-ui","form-builder","json-pointer","json-schema","jsonpath"],"latest_commit_sha":null,"homepage":"https://dashjoin.github.io/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dashjoin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-03-06T16:46:58.000Z","updated_at":"2025-03-01T00:40:15.000Z","dependencies_parsed_at":"2024-05-13T14:58:08.897Z","dependency_job_id":"b992babf-19f8-40c7-9afc-8bde53e9dc22","html_url":"https://github.com/dashjoin/json-schema-form","commit_stats":{"total_commits":305,"total_committers":9,"mean_commits":"33.888888888888886","dds":"0.12459016393442623","last_synced_commit":"58ec1dfc7a1f26e598c71eef257cf17f6065a08f"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dashjoin/json-schema-form","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjson-schema-form","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjson-schema-form/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjson-schema-form/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjson-schema-form/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dashjoin","download_url":"https://codeload.github.com/dashjoin/json-schema-form/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashjoin%2Fjson-schema-form/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265545984,"owners_count":23785892,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular2","autocomplete","declarative-html-form","declarative-ui","form-builder","json-pointer","json-schema","jsonpath"],"created_at":"2025-07-28T00:11:05.350Z","updated_at":"2026-02-25T23:33:36.448Z","avatar_url":"https://github.com/dashjoin.png","language":"TypeScript","readme":"# A Lightweight Angular JSON Schema Form Component\n\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=dashjoin_json-schema-form\u0026metric=alert_status)](https://sonarcloud.io/dashboard?id=dashjoin_json-schema-form)\n[![npm version](https://img.shields.io/npm/v/@dashjoin/json-schema-form.svg?style=flat-square)](https://www.npmjs.com/package/@dashjoin/json-schema-form)\n\n![](https://raw.github.com/jdorn/json-editor/master/jsoneditor.png)\n\n## Goal\n\n* Implement any web form with flexible styling and validation in a completely declarative way\n* Live demo: https://dashjoin.github.io/\n* Stackblitz: https://stackblitz.com/edit/dashjoin\n* [Video Tutorial](https://www.youtube.com/watch?v=Xk9dxbbBFjo)\n\n## Features\n\n* Supports JSON Schema Draft 6\n* Can load referenced schemas from URLs\n* Renders compact forms\n* Supports 2-way databinding\n* Autocomplete \u0026 typeahead based on REST services (complex responses can be processed via extended JSONata)\n* CSS styling\n* Built-in validation\n* Flexible layout options (tab, table, vertical, horizontal, ...)\n* Several input widgets (file upload, date / color picker, autocomplete, ...)\n* Lightweight: \u003c 1000 lines of code\n\n## Installation\n\nTo use the library in your project, follow these steps:\n\n```shell\nnpm i @dashjoin/json-schema-form\nnpm i @angular/material\nnpm i jsonata\n```\n\nIn your app module add:\n\n```typescript\nimport { BrowserModule } from '@angular/platform-browser';\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations';\nimport { JsonSchemaFormModule } from '@dashjoin/json-schema-form';\n...\n\n@NgModule({\n  ...\n  imports: [\n    BrowserModule,\n    BrowserAnimationsModule,\n    JsonSchemaFormModule,\n    ...\n  ],\n  ...\n}\n```\n\nA small sample component:\n\n```typescript\nimport { Component, OnInit } from '@angular/core';\nimport { State } from '@dashjoin/json-schema-form';\nimport { FormArray } from '@angular/forms';\n\n@Component({\n  selector: 'app-root',\n  template: `\n    \u003clib-json-schema-form [state]=\"state\"\u003e\u003c/lib-json-schema-form\u003e\n  `\n})\nexport class AppComponent implements OnInit {\n\n  state: State = {\n    schema: {\n      type: 'array',\n      items: {\n        type: 'object',\n        properties: {\n          name: { type: 'string' },\n          bday: { type: 'string', widget: 'date' }\n        }\n      }\n    },\n    value: [{\n      name: 'Joe',\n      bday: '2018-09-09T22:00:00.000Z'\n    }],\n    name: 'myform',\n\n    // pick FormArray, FormGroup or FormControl for arrays, objects, or single values respectively\n    control: new FormArray([])\n  };\n\n  ngOnInit(): void {\n    // subscribe to form value change / validation or state events\n    this.state.control.valueChanges.subscribe(res =\u003e {\n      console.log(res);\n    })\n  }\n}\n```\n\nFinally, add the material style and icons to styles.css:\n\n```css\n@import \"~@angular/material/prebuilt-themes/indigo-pink.css\";\n@import \"https://fonts.googleapis.com/icon?family=Material+Icons\";\n```\n\n## JSON Schema Extensions\n\nWe define a couple of extensions to JSON Schema in order to define the user interface and layout of the form. Please also see the [demo playground](https://dashjoin.github.io/) where examples of all configuration options are available.\n\n### Widget\n\nThis option specifies a specific input widget to be used. The default is a simple text field. The following options are available:\n\n```\n{\n  \"type\": \"string\",\n  \"widget\": \"date\"\n}\n```\n\n* select: shows a select input field with options (No free text entry is possible. Options can be loaded via rest (see below))\n* upload: the JSON property is set to the contents of an uploaded file\n* date: uses the material date picker component\n* textarea: displays a multi line textarea\n* password: input is shown as *****\n* color: shows a color picker widget\n* datetime-local, email, month, tel, time, url, week: uses the browser native [input types](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input)\n\n### Custom Widgets\n\nIt is possible to create custom widgets using the following steps:\n\n* Create a component that extends [BaseComponent](https://github.com/dashjoin/json-schema-form/blob/master/projects/dashjoin/json-schema-form/src/lib/base/base.component.ts). All relevant data such as the applicable subschema and the current value are passed to the component. Make sure to emit value changes via state.control. An example can be found [here](https://github.com/dashjoin/json-schema-form/blob/master/src/app/custom/custom.component.ts)\n* Include the component in your @NgModule declarations\n* In the parent component, add this service to your constructor: private service: JsonSchemaFormService\n* Register your widget in ngOnInit() using this service: this.service.registerComponent('rich-text-editor', CustomComponent);\n* Include the widget in your schema: { \"widget\": \"custom\", \"widgetType\": \"rich-text-editor\" }\n\n### Autocomplete choices\n\nThe following fields control how select and autocomplete options are obtained from a REST backend:\n\n```\n{\n  \"type\": \"string\",\n  \"choicesUrl\": \"/assets/autocomplete-simple.json\",\n  \"choicesVerb\": \"GET\"\n}\n```\n\n* choices: string array that allows defining the choices statically\n* choicesUrl: defines the REST service URL\n* choicesVerb: defines the HTTP verb to use for the REST service URL, default is POST\n* choicesUrlArgs: defines the REST service parameter. The convention is to have a single parameter. Multiple fields need to be wrapped into a single object\n* jsonata: used to transform the REST result into a string array or an array of objects with name and value fields if it is not already in that form.\n  The transformation is expressed using [JSONata](https://jsonata.org/)\n* choicesLoad: determines whether the choices are loaded upon page load (onLoad) or upon focus (onFocus),  which is the default\n\n### Autocomplete and Select Display Names and Values\n\nIf you want the option's control value (what is saved in the form) to be different than the option's display value (what is displayed in the text field),\nthe \"displayWith\" option allows you to do so. The value of \"displayWith\" is the name under which the implementation class to perform this job was registered.\nThe class must implement the [ChoiceHandler](https://github.com/dashjoin/json-schema-form/blob/master/projects/dashjoin/json-schema-form/src/lib/choice.ts) interface. An example can be found at the end of the [playground component](https://github.com/dashjoin/json-schema-form/blob/master/src/app/app.component.ts).\nThe registration can be done in ngOnInit() using this service: this.service.registerDisplayWith('states', new MyDisplayer()); Consider the following example:\n\n```\n{\n  \"type\": \"string\",\n  \"displayWith\": \"localName\",\n  \"choices\": [\n    \"https://en.wikipedia.org/wiki/Indonesia\",\n    \"https://en.wikipedia.org/wiki/Peru\",\n    \"As is - no tooltip\"\n  ]\n}\n```\n\nThe autocomplete is configured with \"localName\" which is a built-in displayer.\nIt treats options like URLs and displays the local name which is the text after the last slash, hash, colon or dot. This causes the dropdown to display \"Peru\" with the tooltip indicating the real value \"https://en.wikipedia.org/wiki/Peru\" which is written to the JSON value.\n\nThe custom implementation also enables you to exercise tight control over filtering, typeahead loading of options, and determining the display value.\nFor an example of a typeahead implementation, see the class MyTypeAhead at the bottom of the [playground component](https://github.com/dashjoin/json-schema-form/blob/master/src/app/app.component.ts).\n\n### Layout options\n\nLayout options determine how the input elements of arrays and objects are arranged. These options can be applied for each nesting layer (e.g. if you're entering an array of objects):\n\n```\n{\n  \"type\": \"array\",\n  \"layout\": \"horizontal\",\n  \"items\": {\n    \"type\": \"object\",\n    \"layout\": \"vertical\",\n    \"properties\": {\n      \"name\": {\n        \"type\": \"string\"\n      },\n      \"version\": {\n        \"type\": \"number\"\n      }\n    }\n  }\n}\n```\n\n* horizontal (default): input controls are arranged horizontally and flex-wrap if there is insufficient space\n* vertical: input controls are arranged vertically\n* tab: controls are shown in tabs (only applies to arrays and objects with additionalProperties)\n* table: controls are shown in a table with the property names being the column names (only applies to an array of objects)\n* select: array is shown as a multi-select (only applies to arrays of string)\n* Any element can be placed in an expansion panel by adding \"expanded\": true / false. The Boolean value indicates whether the panel is expanded by default or not\n\nThe order field allows to control the inputs of objects:\n\n* The order field can be a list of field names. For example \"order\": [\"firstname\", \"lastname\"] defines the first name input to appear before the last name, regardless of their order in the properties\n* If a property is omitted, the form does not display an input. So in the example above, an age field is not in the form even if it is listed in properties.\n* Order can also specify a 2-level hierarchy like \"order\": [[\"firstname\", \"lastname\"], \"emails\"]. If a vertical layout is chosen, this displays firstname and lastname in the first row and the array of emails in the second row. The first row automatically chooses the opposite layout direction internally.\n\nThe style and class fields allow passing CSS styles and classes to the input fields. For instance, you could emphasize\nthe input with a higher z elevation and accommodate for longer\ninput values by increasing the default input element width:\n\n```\n{\n  \"type\": \"string\",\n  \"class\": [\n    \"mat-elevation-z2\"\n  ],\n  \"style\": {\n    \"width\": \"400px\"\n  }\n}\n```\n\nPlease also see the definition of the [Schema](https://github.com/dashjoin/json-schema-form/blob/master/projects/dashjoin/json-schema-form/src/lib/schema.ts) object.\n\n### Application Logic\n\nIn some situations, you would like to compute a field based on the contents of other fields.\nThis can be achieved via the \"compute\" option. It can be placed within an object as follows:\n\n```\n{\n  \"type\": \"object\",\n  \"properties\": { \"first\": {\"type\": \"string\"}, \"last\": { \"type\": \"string\" }, \"salutation\": { \"type\": \"string\", \"readOnly\": true } },\n  \"computed\": {\n    \"salutation\": '\"Dear \" \u0026 first \u0026 \" \" \u0026 last \u0026 \",\" \u0026 $context(\"var\")'\n  }\n}\n```\n\nIn this example, any change to the first or last fields trigger a change in salutation which is displayed as a read only form field.\nThe expression defining the salutation value is expressed in JSONata (\u003chttps://jsonata.org/\u003e).\nThe custom function $context allows the host application to reference data which was set via this.service.setContext(key, value).\n\n## Validation and Submitting\n\nSome JSON Schema constructs like \"pattern\" or \"required\" allow validating an object against the schema.\nThe result of this validation is displayed on the UI but it is also propagated to the parent component\nvia the \"error\" output variable. Error contains the first validation error message or null if the form is\nvalid. The following example shows how this information can be used to deactivate form submission:\n\n```\n\u003clib-json-schema-form [(value)]=\"value\" [schema]=\"schema\" [label]=\"schema.title\" (errorChange)=\"error=$event\"\u003e\n\u003c/lib-json-schema-form\u003e\n\u003cbutton [disabled]=\"error !== null\" (click)=\"submit()\"\u003eSubmit\u003c/button\u003e\n```\n\nNote that not all JSON schema validation constructs are supported. Also, arrays and\nadditional property objects do not propagate the information and the invalid value is undefined.\n\n## Unsupported JSON Schema properties\n\nWe support JSON Schema Draft 6 with these exceptions:\n\n* patternProperties: allows defining a property type depending on the property name. You can work around this using additionalProperties.\n* const: allows defining a value to be constant. Work around this using default and /or enum with a single option.\n* Combining schemas (oneOf, anyOf, not, allOf): this allows giving multiple options (schemas) for a property. These constructs make a lot of sense for validation but are hard to apply in the context of a form and therefore, they are not supported.\n* contains: specifies that an array must contain one instance of a given type. As with the schema combination constructs, this makes sense for validation for not for forms.\n\n## Referenced Schemas\n\nIn order to foster reuse, schemas are often made available on the web. In this case, you can use JSON schema's $ref mechanism to have the browser load the schema as follows:\n\n```\n\u003clib-json-schema-form [schema]=\"{$ref:'https://raw.githubusercontent.com/riskine/ontology/master/schemas/core/profession.json'}\"\u003e\n```\n\nThe URL can also be relative to the form's URL:\n\n```\n\u003clib-json-schema-form [schema]=\"{$ref:'schema.json'}\"\u003e\n```\n\nIf you do not want the schema to be downloaded, you can also manually provide referenced schemas via the root schema:\n\n```\n{\n  ...\n  referenced: {\n    'http://example.org/': { $id: 'http://example.org/', ... },\n    'urn:myschema': { $id: 'urn:myschema', ... },\n  }\n}\n```\n\n## Structure of this repository\n\nThe repository contains:\n\n* [The actual library code](https://github.com/dashjoin/json-schema-form/tree/master/projects/dashjoin/json-schema-form/src/lib)\n* [Sources of the online demo playground](https://github.com/dashjoin/json-schema-form/tree/master/src/app)\n\n## Contribute\n\nWe welcome contributions. If you are interested in contributing to Dashjoin, let us know!\nYou'll get to know an open-minded and motivated team working together to build the next generation platform.\n\n* [Join our Slack](https://join.slack.com/t/dashjoin/shared_invite/zt-1274qbzq9-mwxBq4WwSTJsITjrvYV4pA) and say hello\n* [Follow us](https://twitter.com/dashjoin) on Twitter\n* [Submit](https://github.com/dashjoin/json-schema-form/issues) your ideas by opening an issue with the enhancement label\n* [Help out](https://github.com/dashjoin/json-schema-form/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) by fixing \"a good first issue\"\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashjoin%2Fjson-schema-form","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdashjoin%2Fjson-schema-form","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashjoin%2Fjson-schema-form/lists"}