Reputation: 855
I know how to style it with regular form inputs/selects/etc, but I have switched from using those to Formik Field, and the above doesn't work the same way.
<Formik
initialValues={{
example: ''
}}
validate={(values) => {
const errors = {};
if (!values.example) errors.example = 'Required';
return errors;
}}
onSubmit={this.handleSubmit}
render={formProps => {
return (
<Form>
<Field type='text' name='example' />
<ErrorMessage name='example' />
</Form>
)
}} />
So how would I change the border of the input from whatever it is normally to red if it is empty on submit?
Upvotes: 5
Views: 17615
Reputation: 356
In your top level (S)CSS file, paste
.formkit-outer[data-invalid] {
.formkit-label, .formkit-messages {
@apply tw-text-red;
}
input {
@apply tw-border-red tw-outline-red;
}
}
to have for all form-kit components the following label + input on error:
Note, I used tailwind with the prefix "tw-". You can use your own classes here.
/Edit: Sorry I read FormKit! But maybe a similar way helps others here. I will not delete this post for that reason.
Upvotes: 0
Reputation: 12232
I've built a Component using react-bootstrap based on @gene b. answer
It gets the meta
field from the useField
hook and passes eventual errors to the isInvalid
prop:
isInvalid={meta.touched && meta.error}
Full component for text input:
import React from 'react';
import { useField } from 'formik';
import Form from 'react-bootstrap/Form';
export default function TextInput (props) {
const [field, meta] = useField(props);
return (
<Form.Group controlId={props.name}>
<Form.Label>{props.label}</Form.Label>
<Form.Control
name={props.name}
isInvalid={meta.touched && meta.error}
{...field}
/>
<Form.Control.Feedback type="invalid">
{meta.error}
</Form.Control.Feedback>
</Form.Group>
);
};
Usage
import { Form } from 'formik';
import TextInput from './textInput';
<Form>
<TextInput name="username" label="Username"/>
</Form>
It's worth mention that exists also the isValid
prop that works exactly the opposite way, adding green flag on valid fields.
Upvotes: 0
Reputation: 11996
FYI, the workaround that works for styling error fields (e.g. borders) is given here:
https://stackoverflow.com/a/66395574/1005607
Pretty astonishing that Formik doesn't provide this functionality out of the box, and you have to extend <Field>
with custom code.
But in general, you're not supposed to use Formik's own <Field>
component. Instead you should wire Formik to a component library like Material UI or React-Bootstrap which exposes isInvalid={..}
or error={..}
props on its components. That will allow you to style your controls properly. Here's an example of how to wire Formik to React-Bootstrap: https://react-bootstrap.github.io/components/forms/#forms-validation-libraries If you type into a control, you'll see how its style changes depending on errors.
Upvotes: 3
Reputation: 3833
When i try the technique suggested in the accepted answer for ErrorMessage
component using
<ErrorMessage name="propertyName" style={{ color: 'red'}}/>
it didn't work for me. It worked when i enclosed it inside another container though.
<div style={{ color: 'red'}}>
<ErrorMessage name="propertyName" />
</div>
Hope this helps someone.
Upvotes: 6
Reputation: 1083
You can style Field
and ErrorMessage
components provided by Formik
just like you would style any other component in react. I created a working demo for you here: https://stackblitz.com/edit/react-formik-field-error-styles
Have a look. Continue reading for explanation.
The simplest way would be to use style
prop:
function getStyles(errors, fieldName) {
if (getIn(errors, fieldName)) {
return {
border: '1px solid red'
}
}
}
...
<Field style={getStyles(formProps.errors, 'example')} type='text' name='example' />
...
However, if you need manageable customizations, I would recommend you create a custom component. Field
provides you with a component
prop to which you can assign your own custom component like CustomInput
or something like so:
function getStyles(errors, fieldName) {
if (getIn(errors, fieldName)) {
return {
border: '1px solid red'
}
}
}
function CustomInput({ field, form: { errors } }) {
return <div>
<input {...field} style={getStyles(errors, field.name)} />
<ErrorMessage name={field.name} />
</div>
}
...
<Field component={CustomInput} type="text" name="example" />
...
Upvotes: 7