Vue component form based on JSON Schema
Vue component form based on JSON Schema and Native HTML
  
- Install
- Demo
- Usage
- Features
- Supported Keywords
- Irrelevant (ignored) Keywords
- FormSchema API
* Props
* Events
* Methods
+ form()
- Working with Async Schema
- Working with Vue Router
- Workind with JSON Schema $ref Pointers
- Data Validation
* Native HTML5 Validation
* Custom Validation API
* Custom Validation with AJV
* Disable Native HTML5 Validation
+ Example: Disable Form Validation using novalidate
+ Usecase: Implement Save, Cancel and Submit
- Labels Translation
- Render Form Elements
* Textarea
* File Input
* Hidden Input
* Password Input
* Multiple Checkbox
* Grouped Radio
* Select Input
* Array Input
* Regex Input
* Fieldset Element
- Custom Form Elements
* Elements API
* Custom Elements Example
- Descriptor Interface
- Usecases
* Grouping fields
- Contributing
- License
``sh`
npm install --save @formschema/native
`html
`
- Keywords for Applying Subschemas With Boolean Logic
- Validation Keywords for Any Instance Type
FormSchema uses:
- HTML input text to render schema with type: 'string'number
- HTML input to render schema with type: 'number' | 'integer'hidden
- HTML input to render schema with type: 'null'checkbox
- HTML input to render schema with type: 'boolean'maximum
- Validation Keywords for Numeric Instances (number and integer)
FormSchema parses keywords , minimum, exclusiveMaximum and exclusiveMinimum to generate HTML attributes max and min.maxLength
- Validation Keywords for Strings
FormSchema parses keywords , minLength, pattern to generate HTML attributes maxlength, minlength and pattern.date
- Validation Keywords for Arrays
- Semantic Validation With "format"
FormSchema uses:
- HTML input to render schema with format: 'date'datetime-local
- HTML input to render schema with format: 'date-time'
- HTML input to render schema with format: 'email' | 'idn-email'time
- HTML input to render schema with format: 'time'url
- HTML input to render schema with format: 'uri'
- String-Encoding Non-JSON Data
- Property dependencies and Schema dependencies
- Schema Re-Use With "definitions" (see JSON Schema $ref Pointers)
- Schema Annotations
- type is only supported string value. Array type definition is not supported.
- enum is used to render multiple choices input
- maximum, exclusiveMaximum, minimum and exclusiveMinimum are used to render numeric fields
- multipleOf is used to render the input attribute stepcontentMediaType
- maxLength, minLength, pattern and const are used to render string fields
- items, additionalItems, maxItems, minItems and uniqueItems are used to render array fields
- dependencies is used to implement Property dependencies and Schema dependencies
- contentEncoding
- contentMediaType
- When is equal to text/*, the HTML element is used for renderingcontentMediaType
- When is not equal to text/*, the HTML element with attributes { type: file, accept: contentMediaType } is used for rendering
- title is used to render the input label
- description is used to render the input description
- default is used to define the default input value
- readOnly is used to render a field as an read-only input
Since FormSchema is just a form generator, some JSON Schema validation keywords
are irrelevant:
- contains
- maxProperties
- minProperties
- patternProperties
- additionalProperties
- propertyNames
- not
- writeOnly
- examples
| Name | Type | Description | Default |
| ----------------------------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| schema required | Object | The input JSON Schema object. | |v-model
| | any | Use this directive to create two-way data bindings with the component. It automatically picks the correct way to update the element based on the input type. | undefined |id
| | String | The id property of the Element interface represents the form's identifier, reflecting the id global attribute. | Random unique ID |name
| | String | The name of the form. It must be unique among the forms in a document. | undefined |bracketed-object-input-name
| | Boolean | When set to true (default), checkbox inputs and nested object inputs will * automatically include brackets at the end of their names (e.g. name="grouped-checkbox-fields[]"). Setting this property to false, disables this behaviour. | true |search
| | Boolean | Use this prop to enable search landmark role to identify a section of the page used to search the page, site, or collection of sites. | false |disabled
| | Boolean | Indicates whether the form elements are disabled or not. | false |components
| | ComponentsLib | Use this prop to overwrite the default Native HTML Elements with custom components. | GLOBAL.Elements |descriptor
| | DescriptorInstance | UI Schema Descriptor to use for rendering. | {} |validator
| | Function | The validator function to use to validate data before to emit the input event.field: GenericField
Syntaxfunction validator(field: GenericField): Promise<boolean>
Parameters The field that requests validationfield.id: string The input ID attribute valuefield.name: string The input name attribute valuefield.value: any The input value for validationfield.schema: JsonSchema The JSON Schema object of the inputfield.required: boolean Boolean indicating whether or not the field is mandatoryfield.hasChildren: boolean Boolean indicating whether or not the field has childrenfield.initialValue: any The initial input valuefield.messages: Message[] The input value for validationReturn valuetrue
A promise that return if validation success and false otherwisenull
| |
| Name | Description |
| ------- | ------------------------------------------------------------------------------------------------------------------- |
| input | Fired synchronously when the value of an element is changed.value: any
Arguments |
#### form()
Get the HTML form object reference.
Example
`html
`
Syntax
`typescript`
form(): HTMLFormElement | VNode | undefined
Return value
An HTMLFormElement object or a VNode object describing the form elementundefined
object, or for input JSON schema object.
`html
`
Load an async schema on the beforeRouterEnter hook:
`html
`
To load a JSON Schema with $ref pointers, you need to install an additional
dependency to resolve them:
`js
import $RefParser from 'json-schema-ref-parser';
import FormSchema from '@formschema/native';
import schemaWithPointers from './schema/with-pointers.json';
export default {
components: { FormSchema },
data: () => ({
schema: {}
}),
created () {
$RefParser.dereference(schemaWithPointers)
.then((schema) => {
// schema is the resolved schema that contains your entire JSON`
// Schema, including referenced files, combined into a single object
this.schema = schema;
});
}
}
See json-schema-ref-parser's documentation page
for more details.
keywordTo load a JSON Schema containing allOf keyword, you need to install an
additional dependency json-schema-merge-allof
to help FormSchema to work properly:
`js
import mergeAllOf from 'json-schema-merge-allof';
import FormSchema from '@formschema/native';
import schemaWithAllof from './schema/with-allof.json';
export default {
components: { FormSchema },
data: () => ({
schema: mergeAllOf(schemaWithAllof)
})
}
`
See json-schema-merge-allof's documentation page
for more details.
By default, FormSchema uses basic HTML5 validation by applying validation
attributes on inputs. This is enough for simple schema, but you will need to
dedicated JSON Schema validator if you want to validate complex schema.
For custom validation, you need to provide a validation function prop.
Bellow the custom validation API:
`ts
type MessageInfo = 0;
type MessageSuccess = 1;
type MessageWarining = 2;
type MessageError = 3;
type MessageType = MessageInfo | MessageSuccess | MessageWarining | MessageError;
interface Message {
type?: MessageType;
text: string;
}
interface GenericField
readonly id: string;
readonly key: string;
readonly name: string;
readonly isRoot: boolean;
readonly schema: JsonSchema;
readonly required: boolean;
readonly hasChildren: boolean;
readonly initialValue: TModel;
readonly value: TModel;
readonly messages: Required
clear(): void; // clear field
reset(): void; // reset initial field value
addMessage(message: string, type: MessageType = MessageError): void;
clearMessages(recursive: boolean = false): void;
}
`
Bellow a basic example with the popular AJV
validator:
`html
`
Since FormSchema use the native HTML Form element, attributes novalidate andformvalidate can be used to disable form validation as it described in the
W3C specification:
> If present, they indicate that the form is not to be validated during
submission.
The no-validate state of an element is true if the element is a
submit button
and the element's formnovalidate attribute is present, or if the element'snovalidate
form owner's
attribute is present, and false otherwise.
#### Example: Disable Form Validation using novalidate
`html`
#### Usecase: Implement Save, Cancel and Submit
Disable the form validation constraints could be useful when implementing a
save feature to the form:
- The user should be able to save their progress even though they haven't fully entered the data in the form
- The user should be able to cancel the saved form data
- The user should be able to submit form data with validation
`html`
The simple way to translate labels without to change the JSON Schema file is to
use a descriptor.
Here an example with Vue I18n:
`html
`
Add a text/* media types to a string schema to render a Textarea element.
Example schema.json
`json`
{
"type": "string",
"contentMediaType": "text/plain"
}
You can also use a descriptor to force the Render to use a Textarea
element:
Example descriptor.json
`json`
{
"kind": "textarea"
}
String schemas with media types not starting with text/* are automatically render as Input File elements.
Example schema.json
`json`
{
"type": "string",
"contentMediaType": "image/png"
}
> There is a list of MIME types officially registered by the IANA,
but the set of types supported will be application and operating system
dependent. Mozilla Developer Network also maintains a
shorter list of MIME types that are important for the web.
Schemas with descriptor's kind hidden are render as hidden input elements.
Example schema.json
`json`
{
"type": "string"
}
Example descriptor.json
`json`
{
"kind": "hidden"
}
String schemas with a descriptor's kind password are used to render Input
Password elements.
Example schema.json
`json`
{
"type": "string"
}
Example descriptor.json
`json`
{
"kind": "password"
}
To define multiple checkbox, use the JSON Schema keyword enum
and uniqueItems:
Example schema.json
`json`
{
"type": "array",
"uniqueItems": true,
"enum": {
"type": "string",
"enum": [
"daily",
"promotion"
]
}
}
Example descriptor.json
`json`
{
"items": {
"daily": {
"label": "Receive daily updates"
},
"promotion": {
"label": "Receive promotion emails"
}
}
}
To group radio elements, use the JSON Schema keyword enum
with a enum descriptor:
Example schema.json
`json`
{
"type": "string",
"enum": [
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
"sunday"
]
}
Example descriptor.json
`json`
{
"kind": "enum",
"items": {
"monday": { "label": "Monday" },
"tuesday": { "label": "Tuesday" },
"wednesday": { "label": "Wednesday" },
"thursday": { "label": "Thursday" },
"friday": { "label": "Friday" },
"saturday": { "label": "Saturday" },
"sunday": { "label": "Sunday" }
}
}
To group HTML Select element, use the JSON Schema keyword enum
with a list descriptor:
Example schema.json
`json`
{
"type": "string",
"enum": [
"monday",
"tuesday",
"wednesday",
"thruday",
"friday",
"saturday",
"sunday"
]
}
Example descriptor.json
`json`
{
"kind": "list",
"items": {
"monday": { "label": "Monday" },
"tuesday": { "label": "Tuesday" },
"wednesday": { "label": "Wednesday" },
"thursday": { "label": "Thursday" },
"friday": { "label": "Friday" },
"saturday": { "label": "Saturday" },
"sunday": { "label": "Sunday" }
}
}
To render a array field, define your schema like:
Example schema.json
`json`
{
"type": "array",
"items": {
"type": "string"
}
}
FormSchema will render a text input by adding a button to add more inputs.
To render a regex input,
define your schema like:
Example schema.json
`json`
{
"type": "string",
"pattern": "[a-e]+"
}
FormSchema use a