Skip to main content

Creating widgets

Sometimes you need to make custom widgets if you need more control over the markup or need to introduce new functionality into your forms.

A very basic example​

The example below is the smallest possible working example for creating a widget:

import React from "react";
import { createForm, textField, StatefulFormView, widget } from "@fab4m/fab4m";
import "@fab4m/fab4m/css/basic/basic.css";

const customTextFieldWidget = widget({
type: {
widget: (props) => {
return (
<input
type="text"
name={props.name}
id={props.id}
required={props.component.required}
disabled={props.component.disabled}
value={props.value ?? ""}
onChange={(e) => {
props.onChange(e.currentTarget.value);
}}
{...props.attributes}
/>
);
},
},
});

const form = createForm({
name: textField({
label: "Your name",
required: true,
widget: customTextFieldWidget,
}),
});

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

Using the fab4m wrapper​

If you want to provide most of the basic functionality that is provided with the standard fab4m widgets you can wrap your widget in the FormComponentWrapper component.

import React from "react";
import {
createForm,
textField,
StatefulFormView,
widget,
FormComponentWrapper,
} from "@fab4m/fab4m";
import "@fab4m/fab4m/css/basic/basic.css";

const fab4mWidget = widget({
type: {
widget: (props) => {
return (
<FormComponentWrapper {...props}>
<input
type="text"
name={props.name}
id={props.id}
required={props.component.required}
disabled={props.component.disabled}
value={props.value ?? ""}
onChange={(e) => {
props.onChange(e.currentTarget.value);
}}
{...props.attributes}
/>
</FormComponentWrapper>
);
},
},
});

const form = createForm({
name: textField({
label: "Your name",
required: true,
widget: fab4mWidget,
}),
});

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

Typescript support​

You can define the data type that the widget is operating on, as well as the settings type that the widget is using (see the next section):

import React from "react";
import { createForm, textField, StatefulFormView, widget } from "@fab4m/fab4m";
import "@fab4m/fab4m/css/basic/basic.css";

const customTextFieldWidget = widget<string>({
type: {
widget: (props) => {
return (
<input
type="text"
name={props.name}
id={props.id}
required={props.component.required}
disabled={props.component.disabled}
value={props.value ?? ""}
onChange={(e) => {
props.onChange(e.currentTarget.value);
}}
{...props.attributes}
/>
);
},
},
});

const form = createForm({
name: textField({
label: "Your name",
required: true,
widget: customTextFieldWidget,
}),
});

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

Providing settings for your widget​

You can define settings for your widget, in those situations it's best to provide a function to create your widget with the appropriate settings.

import React from "react";
import { createForm, textField, StatefulFormView, widget } from "@fab4m/fab4m";
import "@fab4m/fab4m/css/basic/basic.css";

type CustomWidgetSettings = {
color: string;
};

function myCustomWidget(settings: CustomWidgetSettings) {
return widget<string, CustomWidgetSettings>({
type: {
widget: (props) => {
return (
<input
type="text"
name={props.name}
id={props.id}
style={{ background: props.settings.color }}
required={props.component.required}
disabled={props.component.disabled}
value={props.value ?? ""}
onChange={(e) => {
props.onChange(e.currentTarget.value);
}}
{...props.attributes}
/>
);
},
},
settings,
});
}

const form = createForm({
name: textField({
label: "Your name",
required: true,
widget: myCustomWidget({ color: "blue" }),
}),
});

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