Skip to main content

Event Handlers

React-Forminate provides enhanced event handlers that give you access to the complete form context when handling user interactions. These custom events offer more functionality than standard React events while maintaining familiar patterns.

Available Events

EventDescriptionEquivalent DOM Event
onCustomChangeTriggered when field value changesonChange
onCustomBlurTriggered when field loses focusonBlur
onCustomFocusTriggered when field receives focusonFocus
onCustomClickTriggered on mouse clickonClick
onCustomKeyDownTriggered on key press downonKeyDown
onCustomKeyUpTriggered on key releaseonKeyUp
onCustomMouseEnterTriggered when mouse enters fieldonMouseEnter
onCustomMouseLeaveTriggered when mouse leaves fieldonMouseLeave
onCustomMouseDownTriggered on mouse button downonMouseDown
onCustomContextMenuTriggered on right-clickonContextMenu
onCustomUploadSpecial handler for file uploads-
onCustomRemoveSpecial handler for file removal-

Event Handler Signature

All custom event handlers receive the following parameters:

(
event: React.SyntheticEvent,
fieldId: string,
values: Record<string, any>,
fieldSchema: FormFieldType,
formSchema: FormDataCollectionType
) => void

Usage Examples

Basic Change Handler

{
fieldId: "username",
type: "text",
events: {
onCustomChange: (e, fieldId, values) => {
console.log(`${fieldId} changed to:`, values[fieldId]);
}
}
}

File Upload Handling

{
fieldId: "documents",
type: "file",
multiple: true,
events: {
onCustomUpload: (files, fieldId) => {
// Process uploaded files
uploadToServer(files).then(() => {
console.log(`${files.length} files uploaded`);
});
},
onCustomRemove: (file) => {
// Handle file removal
removeFromServer(file);
}
}
}

Keyboard Interactions

{
fieldId: "search",
type: "text",
events: {
onCustomKeyDown: (e, fieldId, values) => {
if (e.key === "Enter") {
searchProducts(values[fieldId]);
}
}
}
}

Context Menu Handling

{
fieldId: "notes",
type: "textarea",
events: {
onCustomContextMenu: (e, fieldId) => {
e.preventDefault();
showCustomMenu(fieldId, e.clientX, e.clientY);
}
}
}

Complete Example

const ProductForm = {
formId: "productForm",
fields: [
{
fieldId: "productName",
type: "text",
label: "Product Name",
events: {
onCustomChange: (e, fieldId, values) => {
analytics.trackFieldChange(fieldId, values[fieldId]);
},
onCustomBlur: () => {
console.log("Product name field lost focus");
}
}
},
{
fieldId: "price",
type: "number",
label: "Price",
events: {
onCustomKeyDown: (e) => {
// Prevent non-numeric input
if (!/[0-9.]/.test(e.key) && e.key !== "Backspace") {
e.preventDefault();
}
}
}
},
{
fieldId: "images",
type: "file",
multiple: true,
accept: "image/*",
events: {
onCustomUpload: (files) => {
// Optimize images before upload
optimizeImages(files).then(optimized => {
uploadImages(optimized);
});
},
onCustomRemove: (file) => {
removeImage(file.name);
}
}
},
{
fieldId: "description",
type: "textarea",
events: {
onCustomFocus: () => {
help.showTooltip("descriptionHelp");
},
onCustomMouseEnter: () => {
preview.showDescriptionPreview();
},
onCustomMouseLeave: () => {
preview.hideDescriptionPreview();
}
}
},
{
fieldId: "submit",
type: "button",
events: {
onCustomClick: (e, _, values) => {
e.preventDefault();
if (validateForm(values)) {
submitForm(values);
}
}
}
}
]
};
Clicky