@modular-forms/solid
Version:
The modular and type-safe form library for SolidJS
73 lines (72 loc) • 2.8 kB
JSX
import { createEffect, createMemo, untrack, mergeProps, } from 'solid-js';
import { createLifecycle } from '../primitives';
import { getElementInput, handleFieldEvent, initializeFieldStore, } from '../utils';
/**
* Headless form field that provides reactive properties and state.
*/
export function Field(props) {
// Get store of specified field
const getField = createMemo(() => initializeFieldStore(props.of, props.name));
// Create lifecycle of field
// eslint-disable-next-line solid/reactivity
createLifecycle(mergeProps({ getStore: getField }, props));
return (<>
{props.children({
get name() {
return props.name;
},
get value() {
return getField().value.get();
},
get error() {
return getField().error.get();
},
get active() {
return getField().active.get();
},
get touched() {
return getField().touched.get();
},
get dirty() {
return getField().dirty.get();
},
}, {
get name() {
return props.name;
},
get autofocus() {
return !!getField().error.get();
},
ref(element) {
// Add element to elements
getField().elements.set((elements) => [...elements, element]);
// Create effect that replaces initial input and input of field with
// initial input of element if both is "undefined", so that dirty
// state also resets to "false" when user removes input
createEffect(() => {
if (element.type !== 'radio' &&
getField().startValue.get() === undefined &&
untrack(getField().value.get) === undefined) {
const input = getElementInput(element, getField(), props.type);
getField().startValue.set(() => input);
getField().value.set(() => input);
}
});
},
onInput(event) {
handleFieldEvent(props.of, getField(), props.name, event, ['touched', 'input'], getElementInput(event.currentTarget, getField(), props.type));
},
onChange(event) {
handleFieldEvent(props.of, getField(), props.name, event, [
'change',
]);
},
onBlur(event) {
handleFieldEvent(props.of, getField(), props.name, event, [
'touched',
'blur',
]);
},
})}
</>);
}