Skip to content
Playground

Migration from v1

Version 2 brings a lot of changes, but most of them relate to the internal mechanisms of the library and in most cases it will be enough for you to switch to the current syntax without semantic changes.

Now:

  • createForm3 -> createForm
  • createValidator2 -> createFormValidator
  • RawForm -> BasicForm
  • Form2 -> SimpleForm

The logic behind component naming is as follows: BasicForm - provides only basic functionality, while SimpleForm - provides a simple way to instantiate a form.

This change allows fields, widget templates and components to be overridden/added simultaneously and type-safe thanks to the @sjsf/form/lib/resolver library.

To make it work you need to remove ... before theme.

import { theme } from 'theme-path'
const form = createForm({ theme, ... })

Example of field override:

import { overrideByRecord } from "@sjsf/form/lib/resolver";
import { theme } from 'theme-path';
import MyField from './my-field';
const myTheme = overrideByRecord(theme, {
fieldTemplate: MyField,
})

The number of components in the default theme has been reduced

Section titled “The number of components in the default theme has been reduced”

It was found out that the following fields and widgets are enough to display any JSON schema:

  • stringField ,numberField ,integerField ,booleanField ,objectField ,arrayField ,tupleField ,nullField ,oneOfField ,anyOfField
  • textWidget, numberWidget, selectWidget, checkboxWidget

Therefore, all other fields and widgets are placed in optional extra modules.

You can import them directly or use special imports to connect them automatically.

// Include extra fields
import "@sjsf/form/fields/extra-fields/boolean-select-include";
import "@sjsf/form/fields/extra-fields/enum-include";
import "@sjsf/form/fields/extra-fields/file-include";
import "@sjsf/form/fields/extra-fields/files-include";
import "@sjsf/form/fields/extra-fields/multi-enum-include";
// Include extra widget for basic theme
import { theme } from "@sjsf/basic-theme";
import '@sjsf/basic-theme/extra-widgets/checkboxes-include';
import '@sjsf/basic-theme/extra-widgets/file-include';
import "@sjsf/basic-theme/extra-widgets/multi-select-include";
import "@sjsf/basic-theme/extra-widgets/textarea-include";
import "@sjsf/basic-theme/extra-widgets/radio-include";
import "@sjsf/basic-theme/extra-widgets/date-picker-include";
const from = createForm({ theme, ... })

However extra fields will not be used automatically, for this you need to use the new resolver property or explicitly replace one field with another in uiSchema.

Previously, the logic for selecting a field to display the schema was spread across multiple components and could not be changed without replacing those components (RootField, ArrayField).

Now this logic is placed in a separate function resolver, which allows to change/extend this algorithm without affecting UI components.

Therefore, you must add this property when calling createForm and SimpleForm

import { resolver } from '@sjsf/from/resolvers/basic'
// Or a variant reproducing the logic of the v1
import { resolver } from '@sjsf/from/resolvers/compat'
const form = createForm({ resolver, ... })

Properties ui:widget, ui:field and ui:templates are merged into ui:components.

This property allows you to replace one component with another if they are compatible.

import MyLayout from "./my-layout.svelte";
const uiSchema: UiSchema = {
"ui:components": {
textWidget: "textareaWidget",
layout: MyLayout,
}
}

Properties such as input, content, container, button and form have been removed from ui:options. Now each theme independently defines a set of ui options allowing to customize its components.

Motivation - different themes use different base components and their properties may not be compatible. For example for textWidget from basic-theme it is HTMLInputAttributes and for flowbite-theme it is InputProps.

Now the validator is just a set of functions:

  • isValid (called to correctly handle the following keywords oneOf, anyOf and if,then,else, required)
  • validateFormValue (optional)
  • validateFormValueAsync (optional)
  • validateFieldValue (optional)
  • validateFieldValueAsync (optional)
  • validateAdditionalPropertyKey (optional)

So now you can easily extend/modify the validator to suit your needs.

import type { ErrorObject } from "ajv";
import { isSchemaObjectValue } from "@sjsf/form/core";
import type { FormValueValidator } from "@sjsf/form";
import { createFormValidator } from "@sjsf/ajv8-validator";
export function createValidator() {
const validator = createFormValidator();
return {
...validator,
validateFormValue(rootSchema, formValue) {
const errors = validator.validateFormValue(rootSchema, formValue);
// Your logic
return errors
},
} satisfies FormValueValidator<ErrorObject>;
}

Checkbox, Range and Switch widgets behavior

Section titled “Checkbox, Range and Switch widgets behavior”

In v1 those widgets would set its field to some default value if its value was undefined (this behavior can be observed when using <input type=“checkbox” bind:checked ... )

In v2 this behavior was removed to keep the behavior uniform with other primitive input elements.

To reproduce the previous behavior, add default: <some default value> to the JSON schema.

There are actually a lot more changes in this release, but considering their nature (mostly internal) and the number of active users at the moment (small relative to rjsf) I think it is not rational to try to create a comprehensive guide.

Feel free to get in touch about migrating to v2 on GitHub or in the Svelte ecosystem discrod channel.