React - react-final-form validation - javascript

I have a question regarding react-final form error message when using record-level validation. I have the following field present within FormFilterFields component.
Field Names:
export const fieldNames = {
password: "field.password"
};
Field:
<Field name={fieldNames.password}>
{({ input, meta }) => {
return (
<div className={styles.textInputContainer}>
<TextInput
type={"password"}
label={"password"}
value={input.value}
onChange={(event)=> {
input.onChange(event)
}}
error={meta.error}
/>
</div>
);
}}
</Field>
Form:
<Form
onSubmit={() => {}}
initialValues={this.props.formValues}
decorators={[formFilterFieldsDecorator]}
validate={values => {
const valuesObject: any = values
const validationErrors = { errors: {} };
if (valuesObject && valuesObject.field.password && valuesObject.field.password.length < 6){
validationErrors.errors.field.password = "password is too short"; //errors.field.password is undefined here
}
return validationErrors;
}}
render={({
handleSubmit,
submitting,
pristine,
values,
form,
invalid
}) => (
<form onSubmit={handleSubmit}>
<FormFilterFields
form={form}
onSubmit={event => this.props.onHandleSubmit(event, values)}
onReset={event => this.props.onHandleReset(event, form)}
/>
<pre>{JSON.stringify(values)}</pre>
</form>
)}
/>
So essentially how would you set the error message for a field name like so:
"field.password"
I have looked at some of the examples but no dice.The alternative would be field level validation which is my last resort as part of my solution.
Any help would be much appreciated
Thanks

Did you try
validationErrors.errors['field.password'] = "password is too short";
Edit
Try this
if (!values.field || !values.field.password) {
errors.field = {password: 'Required'};
}

Related

Redux-from with useState - how to connect with value from redux?

Is it possible to substitute the value from useState with the one coming from input?
Or is there a way to do this using dispatch?
I have tried many ways, but none of them work.
const renderInput = ({
input,
label,
type,
meta: { asyncValidating, touched, error },
}) => {
const [value, setValue] = useState('default state');
const onChange = event => {
setValue(event.target.value);
// + some logic here
};
return (
<div>
<label>{label}</label>
<div className={asyncValidating ? 'async-validating' : ''}>
<input {...input} value={value} onChange={onChange} type={type} placeholder={label} />
{touched && error && <span>{error}</span>}
</div>
</div>
);
};
const SelectingFormValuesForm = props => {
const { type, handleSubmit, pristine, reset, submitting } = props;
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name</label>
<div>
<Field
name="name"
component={renderInput}
type="text"
placeholder="Dish name..."
/>
</div>
</div>
</form>
);
};
SelectingFormValuesForm = reduxForm({
form: 'selectingFormValues',
validate,
asyncValidate,
// asyncBlurFields: ['name'],
})(SelectingFormValuesForm);
export default SelectingFormValuesForm;
This way, unfortunately, the value sent to the submit remains empty.

Trying to make a Formik multistep with validation. How can I validate fields?

I am trying to make a field validation in a formik. The problem is that I made a multi-step form, my approach is that I made an array of components and I use them based on pages[state] and I don't know how to send props to that.
I want to validate the field to take only two digit numbers, and to show a error message if it doesn't
const SignUp = () => {
const state = useSelector((state: RootState) => state);
console.log("state", state);
const dispatch = useDispatch();
return (
<Formik
initialValues={{ firstName: "", lastName: "", email: "" }}
onSubmit={values => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
}, 500);
}}
render={({ errors, touched, isValidating }) => (
<Form>
<div>{pages[state]}</div>
<button
type="button"
onClick={() => {
dispatch(decrement());
}}
>
Prev
</button>
<button
type="button"
onClick={() => {
pages.length - 1 <= state
? console.log("No more pages")
: dispatch(increment());
}}
>
Next
</button>
</Form>
)}
/>
);
};
const Page2 = () => {
return (
<>
<h1>
What is your <span id="idealWeightText">ideal weight</span> that you
want to reach?
</h1>
<Input
name={"firstName"}
htmlFor={"firstName"}
type={"number"}
validation={validateKilograms}
/>
</>
);
};
const Input: React.FC<FieldProps> = ({
name,
onChange,
htmlFor,
type,
validation,
placeholder
}) => {
return (
<>
<label htmlFor={name}>
<Field
type={type}
name={name}
placeholder={placeholder}
validate={validation}
onChange={onChange}
/>
kg
</label>
</>
);
};
There is a library called Yup, That You can use, You will get freedom to set conditional validations.
Yup is best suited with formik for validations.
After Every step You can enable a flag and set the validation accordingly.
Also I would suggest you to use withFormik. Instead of formik because there you can make a separate file for validations and can give its path. So that will also improve your folder structure.

cancel form submit when using formik

first of all thank you so much for your time and good willing to help!
It's the first time I am trying to manage the logic of a form using the formik npm library. It's been really easy to setup and nothing is broken.
But I'm having a problem: The form is being submitted anyway and its causing me troubles because it's redirecting to the /profile and it shouldn't.
This is my form:
<Formik
initialValues={{ identifier: "sdf", password: "fgh" }}
validate={values => {
let errors = {};
// REGEX
let regex = !/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
if (!values.identifier) {
errors.identifier = "El correo electrónico es requerido";
} else if (regex.test(values.identifier)) {
errors.identifier = "Invalid email address";
}
if (!values.password) {
errors.password = "El email es requerido";
}
return errors;
}}
handleSubmit={(values, { setSubmitting }) => {
// trying to see what im receiving.
// I've seen this code searching around and I wanted to try
console.log(values, setSubmitting);
setTimeout(() => {
// submit them do the server. do whatever you like!
alert(JSON.stringify(values, null, 2));
setSubmitting(false);
}, 1000);
}}
onSubmit={values => {
const { identifier, password } = values;
this.context
.login({ identifier, password })
.then(() => {
window.location = "/profile";
this.setState({ isLoading: true, hasErrors: false });
})
.catch(err => {
console.error(err);
this.setState({ isLoading: false, hasErrors: true });
});
}}
render={({
values,
errors,
handleSubmit,
handleChange,
handleBlur
}) => (
<form onSubmit={handleSubmit} name="login">
<Label htmlFor="login__username">
{i18n.FORM.LABEL.USERNAME}
</Label>
{errors.identifier && (
<span color="red">{errors.identifier}</span>
)}
<Input
value={values.identifier}
type="text"
name="login__username"
placeholder={i18n.FORM.LABEL.USERNAME__PLACEHOLDER}
onChange={handleChange}
onBlur={handleBlur}
required
data-cy="identifier"
/>
<Label htmlFor="login__password">
{i18n.FORM.LABEL.PASSWORD}
</Label>
{errors.password && (
<span color="red">{errors.password}</span>
)}
<Input
value={values.password}
type="password"
name="login__password"
placeholder={i18n.FORM.LABEL.PASSWORD__PLACEHOLDER}
onChange={handleChange}
onBlur={handleBlur}
required
data-cy="password"
/>
<ActionsWrapper theme={theme}>
<Button type="submit" size="large" fullWidth>
{i18n.PAGE.LOGIN.BUTTON__SUBMIT}
</Button>
</ActionsWrapper>
</form>
)}
/>
And the function that handles the submit of the form is the one below:
handleOnSubmit = values => {
const { identifier, password } = values;
this.context
.login({ identifier, password })
.then(() => {
window.location = "/profile";
this.setState({ isLoading: true, hasErrors: false });
})
.catch(err => {
console.error(err);
this.setState({ isLoading: false, hasErrors: true });
});
};
I've tried to search how people deals with this but, all the examples I've found did not use anything or care about the prevent of the form.
Why is that? What I'm doing wrong? Any advice? Resources?
Thank you so much for everything!
that's not the default behavior of Forms integrated with formik.
Firstly, I think you're missing the "noValidate=true" attribute on your html form element.
Secondly, I don't think you need "handleSubmit" prop on the Formik tag. Just the onSubmit prop works.

How to make validation to work for redux-form field generated from an array

I am trying to use redux-form to generate a quiz form. My data source for an individual redux-form field component comes from an array - questions in my case. Everything works as expected except validation. Any thoughts how this can be fixed?
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import { Input, Button } from 'reactstrap';
const validate = values => {
const errors = {};
if (!values.question) { // this is just an example of what I am trying to do, validation does not work
errors.question = 'Required';
} else if (values.question.length < 15) {
errors.question = 'Must be 15 characters or more';
}
return errors;
};
const renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<Input {...input} type={type} />
{touched && (error && <span>{error}</span>)}
</div>
</div>
);
const renderQuestions = questions => {
return questions.map(question => {
return (
<Field key={question.id} name={question.prompt} type="textarea" component={renderField} label={question.prompt} />
);
});
};
const QuizStepForm = props => {
const { handleSubmit, pristine, reset, submitting, questions } = props;
return (
<form onSubmit={handleSubmit}>
<Field name="username" type="textarea" component={renderField} label="username" />
{renderQuestions(questions)}
<div>
<br />
<Button color="primary" style={{ margin: '10px' }} type="submit" disabled={submitting}>
Submit
</Button>
<Button type="button" disabled={pristine || submitting} onClick={reset}>
Clear Values
</Button>
</div>
</form>
);
};
export default reduxForm({
form: 'quizStepForm',
validate
})(QuizStepForm);
Your validation function assumes there is one field named "question." But your code creates a set of fields whose name is set by {question.prompt}. If you stick with this implementation, your validation code will need to know about all the question.prompt array values and check values[question.prompt] for each one, then set errors[question.prompt] for any failures. That would probably work, though it seems like a suboptimal design.
This might be a good use case for a FieldArray. In FieldArrays, the validation function is called for you on each field; your validation code doesn't have to know the names of all the fields.

redux-form textarea value not updating

I have a redux form with two input fields and one textarea. The input field values are updated for each keypress and the validate function gets the right values. But the textarea keychanges are not reflected in the validate function. Any help ? The entire code is:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form';
import { createPost } from '../actions/index';
const renderInput = ({ input, label, type, meta: { touched, error, warning } }) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type}/>
{touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
);
const renderTextArea = ({textarea, meta: { touched, error, warning }}) => (
<div>
<label>Content</label>
<div>
<span>{textarea}</span>
<textarea {...textarea} placeholder="Content" rows="10" cols="40"></textarea>
{touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
);
class PostsNew extends Component {
render() {
const { handleSubmit, title, categories, content } = this.props;
return (
<form onSubmit={handleSubmit(createPost)}>
<Field name="title" component={renderInput} label="Title" type="text" {...title} />
<Field name="categories" component={renderInput} label="Categories" type="text" {...categories} />
<Field name="content" component={renderTextArea} {...content} />
<button type="submit">Submit</button>
</form>
);
}
}
const validate = values => {
const errors = {}
if (!values.title) {
errors.title = 'Required';
}
if (!values.categories) {
errors.categories = 'Required';
}
console.log("######", values);
console.log("####", values.content);
if (!values.content) {
errors.content = 'Content cannot be empty';
} else if (values.content.length < 3) {
errors.content = 'Content should be more than 3 characters';
}
return errors;
}
export default reduxForm({
form: 'NewPostForm',
validate
})(PostsNew);
The console.log function calls in the validate function return the right value for the two input fields on each keypress but not the value for the content.
If I replace the textarea Field line, with the following line, the content value is correctly logged on each keypress in the text area (but I cannot validate).
Updated line: <Field name="content" component={textarea} {...content} /> that results in the console.log to reflect keypress.
Looks like a classic search-and-replace error. :-)
const renderTextArea = ({textarea, meta: { touched, error, warning }})
^^^^^^^^
There's your problem. The key is input. Try:
const renderTextArea = ({input, meta: { touched, error, warning }}) => (
<div>
<label>Content</label>
<div>
<textarea {...input} placeholder="Content" rows="10" cols="40"/>
{touched && ((error && <span>{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
);

Categories