UNPKG

extpoint-yii2

Version:

JavaScript part for projects on ExtPoint Yii2 Boilerplate and yii2-core

184 lines (160 loc) 6.07 kB
import React from 'react'; import PropTypes from 'prop-types'; import {connect} from 'react-redux'; import {reduxForm, SubmissionError, getFormValues, initialize} from 'redux-form'; import _isEqual from 'lodash-es/isEqual'; import _get from 'lodash-es/get'; import _set from 'lodash-es/set'; import _isUndefined from 'lodash-es/isUndefined'; import {addSecurity, removeSecurity} from 'yii-steroids/actions/fields'; import {getSecurity} from 'yii-steroids/reducers/fields'; import {http, view, clientStorage} from 'components'; import Field from './Field'; class Form extends React.Component { static STORAGE_KEY_PREFIX = 'Form'; static propTypes = { formId: PropTypes.string.isRequired, model: PropTypes.oneOfType([ PropTypes.string, PropTypes.func, ]), prefix: PropTypes.string, action: PropTypes.string, layout: PropTypes.string, layoutCols: PropTypes.arrayOf(PropTypes.number), onSubmit: PropTypes.func, onChange: PropTypes.func, onComplete: PropTypes.func, contentId: PropTypes.string, formValues: PropTypes.object, autoSave: PropTypes.bool, initialValues: PropTypes.object, security: PropTypes.shape({ component: PropTypes.oneOfType([ PropTypes.string, PropTypes.node ]), }), }; static childContextTypes = { model: PropTypes.oneOfType([ PropTypes.string, PropTypes.func, ]), prefix: PropTypes.string, formId: PropTypes.string, layout: PropTypes.string, layoutCols: PropTypes.arrayOf(PropTypes.number), }; constructor() { super(...arguments); this._refContent = null; this._previousNodeParent = null; this._onSubmit = this._onSubmit.bind(this); } getChildContext() { return { model: this.props.model, prefix: this.props.prefix || '', formId: this.props.formId, layout: this.props.layout, layoutCols: this.props.layoutCols, }; } componentWillMount() { if (this.props.autoSave) { const values = clientStorage.get(`${Form.STORAGE_KEY_PREFIX}_${this.props.formId}`); if (values) { this.props.dispatch(initialize(this.props.formId, { ...JSON.parse(values), ...this.props.initialValues, })); } } } componentDidMount() { if (this.props.contentId) { const node = document.getElementById(this.props.contentId); this._previousNodeParent = node.parentNode; this._refContent.appendChild(node); } } componentWillUnmount() { if (this.props.contentId) { this._refContent.appendChild(this._previousNodeParent); } } componentWillReceiveProps(nextProps) { if (!_isEqual(this.props.formValues, nextProps.formValues)) { this._onChange(nextProps.formValues); } } render() { const {handleSubmit, model, formId, children, action, onSubmit, onComplete, ...props} = this.props; // eslint-disable-line no-unused-vars const FormView = this.props.view || view.getFormView('FormView'); return ( <FormView {...props} onSubmit={this.props.handleSubmit(this._onSubmit)} > {children} <span ref={ref => this._refContent = ref} /> {this.props.security && ( <Field {...this.props.security}/> )} </FormView> ); } _onChange(values) { if (this.props.onChange) { this.props.onChange(values); } if (this.props.autoSave) { clientStorage.set(`${Form.STORAGE_KEY_PREFIX}_${this.props.formId}`, JSON.stringify(values)); } } _onSubmit(values) { Object.keys(this.props.formRegisteredFields || {}).forEach(key => { const name = this.props.formRegisteredFields[key].name; if (_isUndefined(_get(values, name))) { _set(values, name, null); } }); if (this.props.onSubmit) { return this.props.onSubmit(values); } return http.post(this.props.action || location.pathname, values) .then(response => { if (response.security) { return new Promise(resolve => { this.props.dispatch(addSecurity(this.props.formId, { ...response.security, onSuccess: data => { this.props.dispatch(removeSecurity(this.props.formId)); resolve(this._onSubmit({...values, ...data})); }, })); }); } if (response.errors) { throw new SubmissionError(response.errors); } if (!response.security) { if (this.props.autoSave) { clientStorage.remove(`${Form.STORAGE_KEY_PREFIX}_${this.props.formId}`); } if (this.props.onComplete) { this.props.onComplete(values, response); } } }); } } export default connect( (state, props) => ({ form: props.formId, formValues: getFormValues(props.formId)(state), formRegisteredFields: _get(state, 'form.' + props.formId + '.registeredFields'), security: getSecurity(state, props.formId), }) )(reduxForm({})(Form));