VJSF 2 compatibility
The v2compat function can be used to produce a schema compatible with VJSF v3. Compatibility is not 100% please test your schemas.
Single properties - Basic types
All basic types are supported : string, number, integer, boolean.
Single properties - Dates
The "date-time" format is not supported yet.
The formats relative to dates are managed using the date and time pickers from Vuetify.
The formatting and the pickers are heavily dependant on the locale option. To customize the formatting you can look at the Formatting functions section in the configuration documentation.
You can define props for the underlying components using the timePickerProps and datePickerProps options.
Notes about timezone management:
- Date-Times are stored with the user's timezone offset (for example 2020-04-03T21:07:43+02:00 instead of the usual result of
toISOString2020-04-03T19:07:43.152Z, this gives more contextual information to your application - Times alone are stored without representing the offset but also without applying it in the first place. Meaning that if the user select 00:00 we will store 00:00:00Z whatever his timezone. This is because without the context of a date timezone management becomes meaningless.
Single properties - Colors
The format hexcolor is used to display a color picker, you can also use the x-display=color-picker annotation. If using the format syntax, please note that hexcolor is not a standard format (I'm pretty sure it was once a proposal) and you might need to declare it with your JSON schema validator.
Example ajv format: ajv.addFormat('hexcolor', /^#[0-9A-Fa-f]{6,8}$/)
You can customize the color picker using either the colorPickerProps option or the x-props annotation.
Single properties - Selects
Enums, oneOfs with const values and the x-fromData annotation can be used to create select fields.
Arrays are represented as multi-value select fields.
If the number of items is too large the select is replaced by a auto-complete except if you force the use of a select using the x-display=select annotation.
The selectAll options can be used to add a "select all" action prepended to the list of items. It is only applied on multi-value select fields (not autocomplete).
Single properties - Selects from HTTP
It is possible to fill selects using the results from HTTP requests.
Inject values coming from the context in the URL and transform the select in an autocomplete by including {q}.
Single properties - Selects with icons
It is possible to select icon values in many ways.
They can be described by code, by SVG values or by URLs.
Possible values can be listed in enums, oneOfs or fetched from HTTP requests.
Single properties - Comboboxes
Anything that can be represented as a select can also be represented as a combobox to allow the user to enter extra values. To do so you can:
- replace a constraining
enumbyexamples - replace a constraining
oneOfby aanyOfwith one open item that permits any extra value - add the
x-display=comboboxannotation to properties withx-fromUrlorx-fromDataannotations
Single properties - Selection controls
It is possible to replace selects by radio, checkbox and switch groups using the x-display annotation with values radio, checkbox and switch.
Single properties - Files
A string property can be rendered as a file upload form if it has the contentMediaType attribute or the x-display=file annotation.
An object property can also be rendered as a file upload. In this case the name, type, size and lastModified subproperties will be filled with metadatas from the uploaded file. By default the data subproperty will contain a reference to a File/Blob object, except if you define its type as string.
Single properties - Markdown editor (beta)
You can edit markdown content using the x-display=markdown annotation.
To do this Vjsf integrates EasyMDE. But to prevent creating a larger distributable it is not declared as a dependency, you need to load it yourself and make it available in global.EasyMDE (or window.EasyMDE). For example:
import EasyMDE from 'easymde/dist/easymde.min.js'
import 'easymde/dist/easymde.min.css'
global.EasyMDE = EasyMDE
Sections - Sections
Children objects are rendered as sections if they have a title.
It is also possible to create sections without nesting levels in your schema by using allOf.
The rendering of sections is customized by the sectionsClass option (margins, and indenting) and the sectionsTitlesClasses (titles sizes ate different section depth).
Sections - Sections as expansion panels
The "rootDisplay" option is not supported in vjsf v3.
Use the x-display="expansion-panels" annotation to display sections as panels. You can also use the rootDisplay option to display root sections as panels regardless of the content of the schema.
You can use the x-propsannotation to configure the rendering of a specific set of expansion panels and the expansionPanelsProps option to configure default rendering of any set of tabs.
Sections - Sections as tabs
The "rootDisplay" option is not supported in vjsf v3.
Use the x-display="tabs" annotation to display sections as tabs. You can also use the rootDisplay option to display root sections as tabs regardless of the content of the schema.
You can use the x-propsannotation to configure the rendering of a specific set of tabs and the tabsProps option to configure default rendering of any set of tabs.
Sections - Sections as stepper
The "rootDisplay" option is not supported in vjsf v3.
Use the x-display="stepper" or x-display="vertical-stepper" annotation to display sections as a stepper. You can also use the rootDisplay option to display root sections as a stepper regardless of the content of the schema.
You can use the x-propsannotation or the stepperProps / verticalStepperProps options to configure rendering.
Arrays of objects - Editable array
Arrays of objects are presented as an editable list of cards.
Each item is validated separately and does not impact global form validity. Saving an item is blocked if it is not valid.
The list is sortable by dragging the card elements.
The most relevant options to customize the rendering of the arrays are arrayItemColProps, arrayItemCardProps and disableSorting.
Arrays of objects - Editable array inline
Editable arrays can be rendered in an inline mode using the editMode=inline option.
The form will use much less dialogs. It is better in the case of nested editable arrays, where the overlapping dialogs become a mess.
Arrays of objects - Prefilled arrays
Prefilled arrays based on HTTP requests are not supported yet in v3.
Arrays can be initialized using a list of values. In this case elements can be edited and sorted but it is not possible to add or remove them.
Objects used to initialize the array are fetched using similar methods as for select fields (fromData, fromUrl).
Arrays of objects - Tuples
Arrays can be defined with multiple item schemas instead of just one. In this case the array has a fixed size and each item is rendered as a property.
This pattern is suitable for lat/lon pairs for example.
Note that to make items of the tuples required you can use the minItems attribute. If an item is filled all previous items are automatically required.
Arrays of objects - Share items across arrays
You can use the annotation x-arrayGroup to signify that some arrays share some common scope. In this case it should be possible to drag and drop or copy and paste items across these arrays.
Dynamic content - Selects of sub-schemas
An object containing a oneOf or anyOf with varying properties can be represented as a select used to switch between the sub-schemas.
A const property is required to be used as unique key of a oneOf element.
Dynamic content - Conditional content (if/then/else)
It is possible to toggle some properties by using the conditional subschemas if/then/else syntax. The simpler use-case is toggling some properties based on a boolean switch.
This functionality requires a JSON schema validator.
If you load third-party.js Ajv will be used along with ajv-formats and ajv-i18n.
Otherwise you can provide Ajv, ajvAddFormats and ajvLocalize as global variables or as options.
Dynamic content - Conditional content (expression)
The JSON schema if/then/else syntax can be cumbersome and dependencies too limited. This is why vjsf accepts the x-if annotation that can contain en evaluated expression. See the Expressions documentation.
WARNING: this syntax is entirely ignored by a JSON schema validator, therefore you can create a situation where the form is valid but the model is actually invalid (for example if you use x-if on a property that is also required).
Dynamic content - Selects with dependencies
It is possible to create a select based on values from another part of the model.
It is also possible to inject properties from the model inside the URL for an HTTP based select.
Dynamic content - Selects with context dependencies
It is possible to create a select based on values that depend both on other parts of the model and on the context.
Dynamic content - Selects with relative dependencies
It is possible to create a select based on values that are read relatively to the current property. Meaning that you can get the current item in an array for example.
Use the special key parent.value to access the value of the parent property. You can also use parent.parent.value, etc.
Dynamic content - Selects with schema dependencies
Using eval-expr is not supported in VJSF 3.
Using expressions in fromData it is possible to mix information from both other parts of the model and other parts of the schema.
This example illustrates this by reusing the oneOf list of values from a property in another while also filtering this oneOf using the current value of the first property. This creates a select based on the selected values of another select that also uses the proper titles.
This example requires the evalMethod=evalExpr or evalMethod=newFunction option. See the Expressions documentation.
Validation - Basic validation
Some JSON schema syntax elements are translated as validation rules: required, length, pattern, etc.
You can also use the x-rules annotation to set custom rules indirectly as strings referencing functions in the rules option.
If you wrap the vjsf element in a v-form the validation mechanisms will work.
Click on the button at bottom-right of the example to trigger validation.
Initial display of validation errors is conditioned by the initialValidation option. By default the errors of properties with already filled values are displayed while pristine properties wait for user interactions or explicit call of validate().
Validation - Sections validation
A section validity depends on the validity of all its children properties.
This is used to display an error color on broken tabs for example.
Click on the button at bottom-right of the example to trigger validation.
Validation - External validator
You can use an external validation tool to handle more complex validation cases, like formats rules combinations with anyOf/oneOf/allOf, etc. Activate this functionality with the useValidator=true option.
The messages will often be less intuitive than when they are created by vjsf itself based on simple rules, but this mechanism can help prevent outputting invalid data.
This functionality requires a JSON schema validator.
Misc json-schema - Default values
The "default" keyword from JSON schema is used to initialize values when they are undefined in the model.
Misc json-schema - Nullable properties
Properties with basic types can support alternative "null" type.
In this case Vjsf will set null values when initializing empty properties or when clearing an existing property.
Misc json-schema - Read only content
All properties with readOnly=true in schema will be rendered as a disabled field. This is propagated downward in the schema, so a read-only object will have all its children rendered as disabled field.
You can also disable the whole form using disableAll=true option.
You can hide a single property using the x-display=hidden annotation or hide by default all read-only properties using the hideReadOnly=true option.
You can also delete all read-only properties with the deleteReadOnly=true option.
Advanced integration - Layout, classes and styles
You can define classes on the wrapping element of each property using the x-class annotation.
To write CSS rules directly on the wrapping element of a property use the x-style annotation.
To customize the responsive layout of your form you can use the x-cols annotation or the fieldColProps option.
There are also many options that can be used to apply classes to different parts of your form: objectContainerClass, sectionsClass, sectionsTitlesClasses, childrenClass, etc.
Advanced integration - Vuetify props
The x-props annotation can be used to add properties to underlying Vuetify components.
This functionality is tightly coupled to Vuetify for simplicity and power.
Advanced integration - Slots
Each property has before, after and default slots. This is true for object containers, arrays, simple properties, etc. Before and after are handy mostly to display paragraphs of texts, titles, etc. Default can be used to entirely rewrite the way the property is rendered.
You can define any slot of the main underlying Vuetify component for each property (append, prepend, etc.).
All slots are passed either as textual content in a x-slots annotation in the schema (markdown supported) or as code inside the <vjsf /> element with a prefix matching the key of the property in the schema.
The markdown parser can be defined using the markdown option. If you use the default third party dependencies it will be markdown-it and it will be initialized with the markdownit option. For example you can use {markdownit: {html: true}} to accept HTML tags inside the markdown content.
You can write code slots used for multiple properties by naming the slot with a custom- prefix and passing this name to the x-display annotation (see custom-string1 in this example).
Advanced integration - Slots and components
The slots can be used to extend vjsf capabilities by integrating third-party elements.
It is recommended to write wrapper components that create the bridge between vjsf and the integrated components.
This example uses the wrapper components available here. Note that these are only examples that you can duplicate and adapt to your needs, they might be completed and extracted in separate modules for direct reuse later on.
Advanced integration - Directives
You can use the x-directives annotation to instantiate Vue directives on the input components used to render properties. This is directly equal to the directives part of a render data object.
Advanced integration - Localization
Localization is managed at three levels:
- the
localeoption is passed to the components that can use it (notably the date-picker) - the
messagesoption is initialized with localized contents in one of the supported languages - the
formatsoption is initialized with formatting methods (date, etc.) that receive a locale as second parameter
Internationalization of the contents of the schemas (titles and descriptions) falls mostly outside the scope of this library.
You should probably use some preprocessing on the schema before passing it to Vjsf.
A possible solution is to use json refs that point to a dynamically modified section of the schema based on current locale.
As a convenience Vjsf replaces the string ~$locale~ with the current locale in all the refs it resolves, so that you can use something like this "title": {"$ref": "#/i18n/~$locale~/mytitle"} which is a limited solution to the problem.
Development - resolved schema
Test case around schema with $ref elements
Development - Selects with prefilled dependencies
This can be buggy and we might lose the content of the dependency
Development - Selects prefilled with http results
This can be buggy and we can lose the pre-selected values.
Inject values coming from the context in the URL and transform the select in an autocomplete by including {q}.
Development - Prefilled Selects
Selects can have initial values and appear checked, as needed
Development - Readonly select with icons
Check rendering of readOnly select.
Development - Additional validation cases
Cases not very informative for users, but useful for devs.
Development - Ignore values with wrong type
Can happen both in case of invalid original data and incompatible schemas in a select.
Development - Large form
Check that everything works smoothly on a quite large form.
Development - Simple array with a required prop
Minimal case to check that validation works properly in in the case of editable arrays.
Development - Nested allOfs and oneOfs
Bug prone situation.
Development - Prefilled array with wrong type in key property
Development - Prefilled array as a dependency
When selecting topic the change event should be emitted after all async operations are finished. See sharedData.asyncOperations in the code.
Development - Array inside a anyof with a value outside enum
This can create an infinite loop.
Development - Enum with a single item as const
Enum with a single item can be used as another way to express const. See issue #212.
Development - Multiple values in a single string
Use the x-separator or separator keyword.
Development - infinite loop
The empty string in default values along with the nesting can create some infinite loops
Development - Rich expression Array
Check if in operator works to display input.
Development - Array item titles from oneOf
Development - Readonly rendering options
Development - String default values
The default value of a string should only be used if is string is not defined, but not if it is empty.