Skip to main content

Component Variants

Component variants allows you to change all aspects of a form component based on the state of the rest of the form.

While rules allows you to show and hide different component based on the form state, variants lets you customize everything.

Here's a simple example where we make the form component required or not, depending on the form state:

import * as React from "react";
import {
textAreaField,
booleanField,
exists,
createForm,
StatefulFormView,
} from "@fab4m/fab4m";

const form = createForm({
likeBio: booleanField({ label: "Do you like to talk about yourself?" }),
bio: [
// This variant is defined like a rule. If the rule is true,
// then the variant is activated.
[
"likeBio",
exists(),
textAreaField({
label: "You have to write your bio now!",
required: true,
}),
],
// You can also provide a component without a rule. If you reach this point,
// then the component will be rendered.
textAreaField({ label: "Biography" }),
],
});

export default function RequiredWhenPresent() {
return <StatefulFormView form={form} hideSubmit={true} />;
}

Variant selection

A variant array is evaluated in order, and the first variant where the rule passes is selected. If you provide a component without a rule, it will always be selected.

import * as React from "react";
import {
booleanField,
textField,
equals,
content,
createForm,
StatefulFormView,
selectWidget,
} from "@fab4m/fab4m";

const form = createForm({
city: textField({
label: "Select your city",
widget: selectWidget(["London", "Paris", "New york"]),
}),
attractions: [
// This variant is defined like a rule. If the rule is true,
// then the variant is activated.
[
"city",
equals("Paris"),
booleanField({
label: "I visited the eiffel tower",
required: true,
}),
],
[
"city",
equals("London"),
booleanField({
label: "I visited Buckinghamn palace",
required: true,
}),
],
[
"city",
equals("New york"),
booleanField({
label: "I visited the statue of liberty",
required: true,
}),
],
content(
{},
() => "Select a city to tell us if you visited a popular attraction!"
),
],
});

export default function VariantSelection() {
return <StatefulFormView form={form} hideSubmit={true} />;
}

A note about variants and JSON Schema

When you use variants, you need to provide the data you want to validate when you generate your JSON Schema, for example:

import * as React from "react";
import * as beautify from "json-beautify";
import {
textField,
equals,
createForm,
StatefulFormView,
selectWidget,
group,
generateSchema,
} from "@fab4m/fab4m";
import { Schema } from "ajv";

const form = createForm({
transport: textField({
label: "How do you get to work?",
required: true,
widget: selectWidget(["Car", "Public transport"]),
}),

questions: [
[
"transport",
equals("Car"),
group(
{ label: "Questions" },
{
car: textField({
label: "What type of car do you have?",
required: true,
}),
},
),
],
[
"transport",
equals("Public transport"),
group(
{ label: "Questions" },
{
publicTransport: textField({
label: "What type of public transport do you use?",
required: true,
}),
},
),
],
],
});

export default function VariantSchema() {
const [schema, changeSchema] = React.useState<string | Schema>(
generateSchema(form),
);
form.onDataChange((data) => {
changeSchema(generateSchema(form, data));
});
return (
<div>
<StatefulFormView form={form} hideSubmit={true} />
<h4>Here's the schema:</h4>
<pre>{beautify.default(schema, null, 2, 80)}</pre>
</div>
);
}