Sorry, but you either have no stories or none are selected somehow.
If the problem persists, check the browser console, or the terminal you've run Storybook from.
Sometimes the inputs informed provides are not good enough. So we decided to
help you out with that! Informed also gives you access to an useField Hook.
Lets say you like informed's text input but you want to show an error and turn
it red when there is an error. You could achieve this with the following code.
import { Form, useField } from 'informed';
const ErrorText = props => {
const { fieldState, fieldApi, render, ref, userProps } = useField(props);
const { value } = fieldState;
const { setValue, setTouched } = fieldApi;
const { onChange, onBlur, ...rest } = userProps;
return render(
<React.Fragment>
<input
{...rest}
ref={ref}
value={!value && value !== 0 ? '' : value}
onChange={e => {
setValue(e.target.value);
if (onChange) {
onChange(e);
}
}}
onBlur={e => {
setTouched(true);
if (onBlur) {
onBlur(e);
}
}}
style={fieldState.error ? { border: 'solid 1px red' } : null}
/>
{fieldState.error ? (
<small style={{ color: 'red' }}>{fieldState.error}</small>
) : null}
</React.Fragment>
);
};
const validate = value => {
return !value || value.length < 5
? 'Field must be at least five characters'
: undefined;
};
<Form id="custom-form">
<label>
First name:
<ErrorText field="name" validateOnChange validateOnBlur />
</label>
<button type="submit">Submit</button>
</Form>;
Here we use the hook useField, BUT, instead of hooking it all up ourselves,
we just spread the informed object onto the input. Its important to note the use of fieldType,
when you want to use the informed object, you need to tell the hook what type of input
your dealing with so it knows how to handle the dom or native event.
import { Form, useField } from 'informed';
const validate = value => {
return !value || value.length < 5
? 'Field must be at least five characters'
: undefined;
};
const ErrorText = (props) => {
const { render, informed, fieldState } = useField({ fieldType: 'text', validate, ...props });
return render(
<>
<input
{...informed}
style={fieldState.error ? { border: 'solid 1px red' } : null}
/>
{fieldState.error ? (
<small style={{ color: 'red' }}>{fieldState.error}</small>
) : null}
</>
);
};
<Form id="custom-form">
<label>
First name:
<ErrorText
field="name"
validateOnChange
validateOnBlur
/>
</label>
<button type="submit">Submit</button>
</Form>;
Because of this design, you can add your very own custom inputs! Below is an example of a slider!
import { Form, asField } from 'informed';
const Slider = asField(({ fieldState, fieldApi, ...props }) => {
const { value } = fieldState;
const { setValue, setTouched } = fieldApi;
const { onChange, onBlur, initialValue, forwardedRef, ...rest } = props;
return (
<input
{...rest}
type="range"
min={0}
max={100}
step={5}
ref={forwardedRef}
value={value || initialValue || '0'}
onChange={e => {
setValue(e.target.value);
if (onChange) {
onChange(e);
}
}}
onBlur={e => {
setTouched(true);
if (onBlur) {
onBlur(e);
}
}}
/>
);
});
<Form id="custom-form">
<label htmlFor="custom-range">Range:</label>
<Slider field="range" id="custom-range" initialValue={50} />
<button type="submit">Submit</button>
</Form>;