@ghalusa/formschemahalusa v1.0.0
FormSchema Native
Vue component form based on JSON Schema and Native HTML
This is the branch for @formschema/native 2.0 Alpha, not ready for production. For the 1x version, please switch to the v1 branch.
Status: Alpha
Core features are not ready and the API could changed. Don't use this in production.
Install
npm install --save @formschema/native
Demo
Usage
<template>
<FormSchema :schema="schema" v-model="model" @submit.prevent="submit">
<button type="submit">Subscribe</button>
</FormSchema>
</template>
<script>
import FormSchema from '@formschema/native'
import schema from './schema/newsletter-subscription.json'
export default {
data: () => ({
schema: schema,
model: {}
}),
methods: {
submit (e) {
// this.model contains the valid data according your JSON Schema.
// You can submit your model to the server here
}
},
components: { FormSchema }
}
</script>
Features
- Keywords for Applying Subschemas With Boolean Logic
- Validation Keywords for Any Instance Type
FormSchema uses:
- HTML input
text
to render schema withtype: 'string'
- HTML input
number
to render schema withtype: 'number' | 'integer'
- HTML input
hidden
to render schema withtype: 'null'
- HTML input
checkbox
to render schema withtype: 'boolean'
- HTML input
- Validation Keywords for Numeric Instances (number and integer)
FormSchema parses keywords
maximum
,minimum
,exclusiveMaximum
andexclusiveMinimum
to generate HTML attributesmax
andmin
. - Validation Keywords for Strings
FormSchema parses keywords
maxLength
,minLength
,pattern
to generate HTML attributesmaxlength
,minlength
andpattern
. - Validation Keywords for Arrays
- Semantic Validation With "format"
FormSchema uses:
- HTML input
date
to render schema withformat: 'date'
- HTML input
datetime-local
to render schema withformat: 'date-time'
- HTML input
email
to render schema withformat: 'email' | 'idn-email'
- HTML input
time
to render schema withformat: 'time'
- HTML input
url
to render schema withformat: 'uri'
- HTML input
- String-Encoding Non-JSON Data
- Property dependencies and Schema dependencies
- Schema Re-Use With "definitions" (see JSON Schema $ref Pointers)
- Schema Annotations
Supported Keywords
- 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
step
- 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
contentMediaType
is equal totext/*
, the HTML element<textarea/>
is used for rendering - When
contentMediaType
is not equal totext/*
, the HTML element<input/>
with attributes{ type: file, accept: contentMediaType }
is used for rendering
- When
- 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
Irrelevant (ignored) Keywords
Since FormSchema is just a form generator, some JSON Schema validation keywords are irrelevant:
- contains
- maxProperties
- minProperties
- patternProperties
- additionalProperties
- propertyNames
- not
- writeOnly
- examples
FormSchema API
props
schema
Object (required)The input JSON Schema object.
v-model
Number|String|Array|Object|Boolean (optional)default: undefined
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.
id
String (optional)The id property of the Element interface represents the form's identifier, reflecting the id global attribute.
name
String (optional)default: undefined
The name of the form. It must be unique among the forms in a document.
bracketed-object-input-name
Boolean (optional)default: true
When set to true (default), checkbox inputs will automatically include brackets at the end of their names (e.g. name="Multicheckbox-Value1[]". Setting this property to false, disables this behaviour.
search
Boolean (optional)default: false
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.disabled
Boolean (optional)default: false
Indicates whether the form elements are disabled or not.
components
Components (optional)default: GLOBAL.components
Use this prop to overwrite the default Native HTML Elements with custom components.
events
input
Fired synchronously when the value of an element is changed.
methods
form()
Get the HTML form reference.
return value:
- HTMLFormElement|VNode|undefined - Returns the HTML form element or
undefined
for empty object
- HTMLFormElement|VNode|undefined - Returns the HTML form element or
Working with Async Schema
<template>
<FormSchema v-model="schema"/>
</template>
<script>
import axios from 'axios'
import FormSchema from '@formschema/native'
export default {
components: { FormSchema },
data: () => ({
schema: {}
}),
created() {
axios.get('/api/schema/subscription.json').then(({ data: schema }) => {
this.schema = schema
});
}
};
</script>
Working with Async Schema and Vue Router
<template>
<FormSchema v-model="schema"/>
</template>
<script>
import axios from 'axios'
import FormSchema from '@formschema/native'
export default {
components: { FormSchema },
data: () => ({
schema: {}
}),
beforeRouterEnter(from, to, next) {
axios.get('/api/schema/subscription.json')
.then(({ data: schema }) => next((vm) => vm.setSchema(schema)))
.catch(next);
},
methods: {
setSchema(schema) {
this.schema = schema;
}
}
};
</script>
Render a Textarea element
Add a text/*
media types to a string schema to render a Textarea element.
Example schema.json
{
"type": "string",
"contentMediaType": "text/plain"
}
You can also use a custom descriptor to force the Render to use a Textarea element:
Example descriptor.json
{
"kind": "textarea"
}
Render an Input File element
String schemas with media types not starting with text/*
are automatically render as Input File elements.
Example schema.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.
Render a hidden Input element
String schemas with defined const
property are automatically render as Input File elements.
Example schema.json
{
"type": "string",
"const": "value of the hidden input"
}
Multiple Checkbox elements
To define multiple checkbox, use the JSON Schema keyword anyOf
:
Example schema.json
{
"type": "object",
"properties": {
"multipleCheckbox": {
"type": "array",
"anyOf": [
"daily",
"promotion"
]
}
}
}
Grouped Radio elements
To group radio elements, use the JSON Schema keyword enum
:
Example schema.json
{
"type": "object",
"properties": {
"groupedRadio": {
"type": "string",
"enum": [
"daily",
"promotion"
]
}
}
}
Array Inputs Elements
To render a array field, define your schema like:
Example schema.json
{
"type": "object",
"properties": {
"arrayInput": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
FormSchema
will render a text input by adding a button to add more inputs.
Regex Inputs
To render a regex input, define your schema like:
Example schema.json
{
"type": "object",
"properties": {
"regexInput": {
"type": "string",
"pattern": "[a-e]+"
}
}
}
JSON Schema $ref Pointers
To load a JSON Schema with $ref
pointers, you need to install an additional dependency to resolve them:
import $RefParser from 'json-schema-ref-parser';
import FormSchema from '@formschema/native';
import schemaWithPointers from './schema/with-pointers.json';
export default {
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;
});
},
components: { FormSchema }
}
See json-schema-ref-parser documentation page for more details.
Custom Form Elements
To define custom elements for rendering, you need to use the Components
class and the components
prop:
// MyCustomElements.js
import { Components } from '@formschela/native';
import { InputElement } from '@/components/InputElement';
import { ArrayElement } from '@/components/ArrayElement';
import { FieldsetElement } from '@/components/FieldsetElement';
import { ListElement } from '@/components/ListElement';
import { TextareaElement } from '@/components/TextareaElement';
import { StateElement } from '@/components/StateElement';
export const MyCustomElements = new Components();
MyCustomElements.set('array', ArrayElement);
MyCustomElements.set('string', InputElement);
MyCustomElements.set('boolean', StateElement);
MyCustomElements.set('radio', StateElement);
MyCustomElements.set('checkbox', StateElement);
MyCustomElements.set('enum', FieldsetElement);
MyCustomElements.set('number', InputElement);
MyCustomElements.set('integer', InputElement);
MyCustomElements.set('object', FieldsetElement);
MyCustomElements.set('list', ListElement);
MyCustomElements.set('textarea', TextareaElement);
See the file NativeElements.ts for an example.
<template>
<FormSchema v-model="model" :schema="schema" :components="components"/>
</template>
<script>
import FormSchema from '@formschema/native'
import { MyCustomElements } from './MyCustomElements'
export default {
data: () => ({
schema: { /* ... */ },
components: MyCustomElements,
model: {}
}),
components: { FormSchema }
}
</script>
- Definition: https://gitlab.com/formschema/components/elementui/blob/master/lib/ElementUIComponents.js
- Usage: https://gitlab.com/formschema/components/elementui/blob/master/playground/src/components/Subscription.vue
Contributing
Please see contributing guide.
License
Under the MIT license. See LICENSE file for more details.
5 years ago