Is there any way to show the server-side (back-end) error on the fields after the submission? The error might be related to specific field or to the form. I searched the doc and also read the source, and I found no way to do it after submit.
Imagine that the response of the submission is a list of errors, how can we pass it to the Form.js to render?
Having {errors, errorSchema} on Form.js props and render it.
Hey. The way to do it is to use the addError method from the custom validation. You have 2 parameters in the validate method errors & formData.
validate = (formData: any, errors: FormValidation): FormValidation => {
console.log("ERRORS", errors);
return errors;
};
<JsonForm validate={this.validate} />
The FormValidation is an object with addError that is a method & __errors that is an array.
In your case i will create a react container to contain your json-form then add extra props like apiErrors,
Find the input name in your error object and call the method addError to add the error message.
It will passing down the rawErrors props to your component.
Hope it help you.
@Vandell63
I suspect if it will work. The problem is that I know the errors after that I submit the form and then I have the server validation errors. And I think the custome validation is being fired before the form submission.
I understand what you trying to say.
Create an hidden button for your form and ref this guy.
Now in your lifecycle component. ComponentWillReceivePros or getDerivedStateFromProps check apiErrors length from your props and reSubmit your form with your refButton: this.submitButton.click()
@Vandell63 Isn't it easier to just change the submit function in Form.js line 153 as follow ?!
setState(this, { errors: [], errorSchema: {} }, () => {
if (this.props.onSubmit) {
const {serverErrors, serverErrorSchema} = this.props.onSubmit({ ...this.state, status: "submitted" });
//new code
//some how we have to be sure that the error objects returned from the props.submit function match the desired format
if (serverErrors && serverErrorSchema) {
setState(this, { errors: serverErrors, errorSchema: serverErrorSchema });
}
//new code end
}
});
Take a look at: #874 , is this what you are waiting for?
@bsvveen fundamentally yes, but I did not like the implementation. it is complicated and not consistent with the other validation work flow. Although passing the errorSchema through props matches the overall react one directional data flow, but it is much simpler, and easier to maintain, to have it implemented as the above suggestion.
I am waiting for the others opinions in order to make the idea mature enough to implement.
OOP save the world.
import Form from 'react-jsonschema-form';
...
class MyServerSideValidationForm extends Form {
onSubmit = async function(event) {
...
this.setState({validating:true});
const { errors, errorSchema } = await myServerSideValidate(this.state.formData);
this.setState({validating:false});
...
}
}
Taking the above work of @knilink a step further, here's what I came up with.
It's essentially monkey-patching the onSubmit() method of Form and adding in a fetch() call. Couldn't get the async / await syntax to play ball though.
To make this really shine it would be worth adding in a loading state as well to show a message to the user while the async validation is being done!
class Form2 extends Form {
onSubmit = event => {
event.preventDefault();
// Client-side validation.
const { errors, errorSchema } = this.validate(this.state.formData);
if (Object.keys(errors).length > 0) {
this.setState({ errors, errorSchema }, () => {
if (this.props.onError) {
this.props.onError(errors);
} else {
console.error("Form validation failed", errors);
}
});
return;
}
// Server-side validation
return fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
// Server-side error? Send to child component's onSubmit() function.
if (json.error) {
this.setState({ errors: [], errorSchema: {} }, () => {
this.props.onSubmit({ ...this.state }, true);
});
return;
}
// All is well.
this.setState({ errors: [], errorSchema: {} }, () => {
if (this.props.onSubmit) {
this.props.onSubmit({ ...this.state, status: "submitted" }, false);
}
});
});
}
}
Then you can do something like this in your component's onSubmit handler:
class MyForm extends Component {
...
handleFormSubmit(data, error) {
if (error) {
this.setState({
formData: data.formData,
formServerSideError: true
})
} else {
this.setState({
formData: {},
});
}
...
}
Merging this issue back in #197 .
Most helpful comment
OOP save the world.