UNPKG

react-browser-form

Version:

<div align="center"> <a href="https://deniskabana.github.io/react-browser-form/introduction" title="React Browser Form - Form management in React made simple for browsers."> <img src="https://raw.githubusercontent.com/deniskabana/react-browser-form/

113 lines (89 loc) 4.58 kB
import { DataFlowState, EventSource, EventType } from "../../types"; import { hydrateDomInputs } from "../../utils/hydrateDomInputs"; import { getDomInputValue } from "../getDomInputValue"; import { hydrateFormState } from "../hydrateFormState"; import { transformValueType } from "../transformValueType"; import { validateFormState } from "../validateFormState"; export function handleChangeEvent<Schema>(dataFlowState: DataFlowState<Schema>): void { const { options } = dataFlowState; // 1. USER CHANGE EVENT // -------------------------------------------------------------------------------- if (dataFlowState.event.source === EventSource.User) { if (dataFlowState.event.type !== EventType.FormInit) { // DEBUG: Feedback for changeReason dataFlowState.changeReason = `Change form values programatically.\nSource: ${dataFlowState.event.source}`; } const eventValue = dataFlowState.event.value; if (!eventValue) return; // 1.1. Set form to dirty and update dirtyFields if (!dataFlowState.isDirty) dataFlowState.setIsDirty(true); dataFlowState.setDirtyFields(Object.keys(eventValue) as Array<keyof Schema>); // 1.2. Populate changedData, quit if no value was provided dataFlowState.changedData = eventValue; // 1.3. Validate form state (validates only changedData) validateFormState(dataFlowState); // 1.4. Populate formState with transformed data // TODO: Figure out a better way to do transformations for (let key in dataFlowState.changedData) { (dataFlowState.formState as any)[key] = transformValueType( key as keyof Schema, dataFlowState.changedData[key], dataFlowState, ); } // 1.5. Hydrate DOM inputs from form state hydrateDomInputs(options, dataFlowState.formState); // 1.6. Trigger callback dataFlowState.callbacks.onChange({ ...dataFlowState.formState }); } // 2. FORM CHANGE EVENT // -------------------------------------------------------------------------------- if (dataFlowState.event.source === EventSource.Form) { const targetInput = dataFlowState.event.nativeEvent?.target as HTMLInputElement; const fieldName = targetInput?.name; if (!targetInput || !fieldName) return; // 2.1. Set form to dirty and update dirtyFields if (!dataFlowState.isDirty && targetInput && fieldName) dataFlowState.setIsDirty(true); dataFlowState.setDirtyFields([fieldName] as Array<keyof Schema>); // 2.2. Conditional execution and revalidation const hasOnChangeMode = options.mode === "onChange"; const isLiveField = options.liveFields.includes(fieldName as keyof Schema); const shouldRevalidate = dataFlowState.errorData.errors[fieldName as keyof Schema] && options.revalidationStrategy === "onChange" && (options.mode === "onBlurUnlessError" || options.mode === "onSubmitUnlessError"); const shouldExecute = hasOnChangeMode || isLiveField || shouldRevalidate; if (!shouldExecute) return; // 2.3. Hydrate form state from DOM inputs hydrateFormState(dataFlowState, [fieldName]); // 2.4. Populate changedData with the single input value that has changed const value = getDomInputValue(dataFlowState); dataFlowState.changedData[fieldName as keyof Schema] = value; // 2.5. Populate formState with transformed data // TODO: Figure out a better way to do transformations dataFlowState.formState[fieldName as keyof Schema] = transformValueType( fieldName as keyof Schema, value, dataFlowState, ); // 2.6. If live field changed, populate changedData with all errored fields for revalidation - live fields are often conditional / dependent if (isLiveField) { for (let key in dataFlowState.errorData.errors) { dataFlowState.changedData[key] = dataFlowState.formState[key]; } } // 2.7. Validate form state (validates only changedData) validateFormState(dataFlowState); // DEBUG: Feedback for changeReason if (hasOnChangeMode) dataFlowState.changeReason = `Changed form state - onChange mode.\nSource: ${dataFlowState.event.source}`; if (shouldRevalidate) dataFlowState.changeReason = `Changed form state - error revalidation.\nSource: ${dataFlowState.event.source}`; if (isLiveField) dataFlowState.changeReason = `Changed form state - live field.\nSource: ${dataFlowState.event.source}`; // 2.8. Trigger callback if (hasOnChangeMode || isLiveField) { dataFlowState.callbacks.onChange(dataFlowState.formState); } } }