Theme

Docs Navigation

Schema

FormKit's schema is a JSON-serializable data format for storing DOM structures and component implementations including FormKit forms. Although created specifically for implementing forms, the format is capable of generating any HTML markup or using any third-party components. Schemas are rendered using FormKit's <FormKitSchema> component.

A schema is an array of objects (called "schema nodes"), where each object defines a single HTML element, component, or text node. Simple strings produce text nodes, while components and HTML elements are defined with two different objects (referred to as $el and $cmp).

HTML elements ($el)

HTML elements are defined using the $el property. You can use $el to render any HTML element. Attributes can be added with the attrs property, and content is assigned with the children property:

Load Live Example
tip
Notice in the above example that the style attribute is unique in that it should be defined as an object of style to value pairs rather than a string.

Components ($cmp)

Components can be defined with the $cmp property. The $cmp property should be a string that references a globally defined component or a component passed into FormKitSchema with the library prop.

Load Live Example
Components as props
In order to pass concrete components via the library prop, it's best to wrap your library with Vue’s markRaw signature.

References

In addition to the schema array (and optional library), the FormKitSchema object can also include a data prop. Values from the data object can then be referenced directly in your schema — and your schema will maintain the reactivity of the original data object.

To reference a value from the data object, you simply use a dollar sign $ followed by the property name from the data object. References can be used in attrs, props, conditionals and as children.

Load Live Example
Important note
Notice in the above example that we used an array to concatenate "Hello" and "$location". We did this because data references and logical expressions in the schema must always begin with a dollar sign $ — otherwise they are treated as unparsed string literals.

Referencing functions

Schemas support calling functions that are in your original reference data — and you can even pass data references as arguments of that function!

Load Live Example

Deep references

Just like JavaScript — you can access properties of a deeply nested object using dot-syntax object.property.

Load Live Example
Reserved words
Schema references can have any structure or properties, but at the root of the data reference object there are 2 reserved words: $slots and $get.

Expressions

Schemas also support logic in the form of boolean logic, comparison, and arithmetic expressions. These expressions can be used anywhere a data reference can be used (attrs, props, conditionals, and children).

Load Live Example
Labeling expressions
Expressions must always begin with a $. If the first element of an expression is a data reference (ex: $count + 2), then it already begins with a $ and no further labeling is required. However, often the first character of an expression is not a dollar sign — these expressions need to be "labeled" with $: — for example $: ($count * 3) - 7.

Although it looks very much like JavaScript — schema expressions are not JavaScript. They are better thought of as a templating language. Expressions are compiled down to functional JavaScript at setup but the syntax is not 1-1 compatible with JavaScript. This improves performance and provides a critical layer of security as only explicitly exposed data and functionality can be executed.

Schema expressions are limited to the following operators and parenthesis:

OperatorUse case
+Addition
-Subtraction
*Multiplication
/Division
%Modulus
&&Boolean AND
||Boolean OR
===Strict equals
!==Strict not equals
==Loose equals
!=Loose not equals
>=Greater than or equal
<=Less than or equal
>Greater than
<Less than

Conditionals

FormKit schema can leverage references and expressions to make schema nodes and attributes conditional. These conditionals can be added in two ways:

  • The if property on $el and $cmp nodes.
  • The if/then/else object

The if property

Both $el and $cmp schema nodes can leverage an if property that roughly equates to a v-if in Vue. If the expression assigned to the if property is truthy, the node is rendered, otherwise it is not.

Load Live Example

The if/then/else object

The if/then/else object allows for more complex conditional logic. It can be used to conditionally render nodes, a list of schema nodes, values of the attrs object or values of the props object. It is also possible to nest if/then/else objects to create more complex structures — similar to an else if statement in JavaScript.

Using if/then/else on schema nodes

You can use the if/then/else object anywhere you would normally use a schema node. This includes the root schema array, or the children property of another schema node.

Load Live Example

Using if/then/else on attrs and props

You can also use if/then/else statements to conditionally output the values of attrs or props.

Load Live Example

Loops

Both $el and $cmp schema nodes support looping. The loop syntax is similar to v-for in Vue and expects an object or array to iterate over and a property to assign the current iteration value to. Optionally, you can also capture the index or property of the current iteration.

Load Live Example
Casting
Sometimes schema expressions need to cast a string to a number. For example, keys are always string values during an iteration, so in the above example it was necessary to cast $key to an integer before adding it to 1. To perform this cast, we simply multiplied by 1: $key * 1 before performing our addition.

Slots

Schemas can render the slot content of the <FormKitSchema> component anywhere within the schema that a normal schema node can be rendered. All scoped slots are automatically provided to the schema under the $slots reference object.

Load Live Example

Binding attrs and props

At times it may be necessary to pass an object of variable or unknown attributes or props to a $cmp or $el. In Vue we would do this using v-bind — in schema land we use the bind property:

Load Live Example

Raw values

At times it may be necessary to prevent a given attribute or prop from being parsed. This can be done by prefixing an attribute or prop with __raw__.

In the above example, the __raw__ prefix will be removed, and the unparsed value of $2.99 will be passed as the price prop to the PriceComponent.

Another scenario where this comes into play is rendering FormKit components. The <FormKit> component has a sections-schema prop that allows users to pass down schema partials to merge with various sections of their input. In this edge case, we want to pass the schema chunks to the <FormKit> component as a raw JavaScript object. To do so, we once again prefix the sectionsSchema prop with __raw__:

Load Live Example

Notice if you remove the __raw__ prefix from the above example, the prefix no longer has effect — this is because the sectionsSchema prop’s value was parsed when creating the component instead of passed as a JavaScript object.

FormKit Inputs

Although schemas can be used for almost any purpose — the primary objective is to empower developers to build complex and dynamic forms using a serializable data format. Using the schema with FormKit inputs covers this use case well.

Assuming you globally registered the FormKit component — you can render your FormKit inputs from schema by using the $cmp schema node.

Load Live Example

Accessing other inputs

The schema format has one built-in function specific to FormKit inputs: the $get function. This builtin allows the schema to access the context object of any other FormKit input (even outside the immediate form) — provided the input in question has an explicitly declared id prop. This allows the schema to respond conditionally to the state of your own inputs.

Load Live Example