react-redux-form-validation
Version:
Custom validation with redux-forms
92 lines (75 loc) • 3.11 kB
JavaScript
import PT from 'prop-types';
import React, { createElement, Component } from 'react';
import { findDOMNode } from 'react-dom';
import { Fields, reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import { feedbackSummaryFactory } from './feedback-summary';
import validation from './validate';
function getSubmittokenFromStore(form) {
return (state, ownProps) => {
const formname = ownProps.form || form;
return ({
submittoken: state.form[formname].submittoken
});
};
}
export default function validForm(config) {
const { form, errorSummaryTitle, validate, listCreator, elementCreator, ...rest } = config;
const defaultSummary = feedbackSummaryFactory(listCreator, elementCreator);
const fields = Object.keys(validate || {});
return (WrappedComponent) => {
const mappedConfig = {
form,
validate: validation(validate),
...rest
};
class Wrapper extends Component {
constructor(props) {
super(props);
this.handleSubmitProxy = this.handleSubmitProxy.bind(this);
}
handleSubmitProxy(...args) {
return Promise.resolve(this.props.handleSubmit(...args))
.then((result) => {
if (typeof result !== 'object') {
// Resolved ok from onSubmit promise
return result;
}
// Rejected from onSubmit promise
// Result contains keys from fields, then it had a validation error
const hasField = Object.keys(result)
.find((errorField) => fields.includes(errorField));
if (hasField) {
const summary = this.summaryPanel.getRenderedComponent();
findDOMNode(summary).focus(); // eslint-disable-line react/no-find-dom-node
}
return result;
});
}
render() {
const { submittoken, ...props } = this.props;
const errorSummary = (
<Fields
names={fields}
header={errorSummaryTitle}
component={defaultSummary}
submittoken={submittoken}
withRef
ref={(panel) => { this.summaryPanel = panel; }}
/>
);
const useProps = {
...props,
errorSummary,
handleSubmit: this.handleSubmitProxy
};
return createElement(WrappedComponent, useProps);
}
}
Wrapper.propTypes = {
handleSubmit: PT.func.isRequired,
submittoken: PT.string
};
return reduxForm(mappedConfig)(connect(getSubmittokenFromStore(form))(Wrapper));
};
}