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:
- Code
- Example
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.
- Code
- Example
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):
- Code
- Example
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.
- Code
- Example
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} />;
}