UNPKG

8.49 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _react = require('react');
8
9var _react2 = _interopRequireDefault(_react);
10
11var _propTypes = require('prop-types');
12
13var _propTypes2 = _interopRequireDefault(_propTypes);
14
15var _debounce = require('lodash/debounce');
16
17var _debounce2 = _interopRequireDefault(_debounce);
18
19var _validation = require('../../utilities/validation');
20
21var _form = require('../../utilities/form');
22
23var _immutable = require('immutable');
24
25var _style = require('./style.scss');
26
27var _style2 = _interopRequireDefault(_style);
28
29var _OptClass = require('../internal/OptClass');
30
31var _OptClass2 = _interopRequireDefault(_OptClass);
32
33function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
34
35function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
36
37function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
38
39function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
40
41var FormGroup = function (_React$Component) {
42 _inherits(FormGroup, _React$Component);
43
44 function FormGroup(props) {
45 _classCallCheck(this, FormGroup);
46
47 var _this = _possibleConstructorReturn(this, (FormGroup.__proto__ || Object.getPrototypeOf(FormGroup)).call(this, props));
48
49 _this.state = {
50 fieldErrors: (0, _immutable.Map)()
51 };
52
53 _this.UNSAFE_componentWillReceiveProps = function (nextProps) {
54 var nextPropsSchema = (0, _immutable.fromJS)(nextProps.schema);
55 var thisPropsSchema = (0, _immutable.fromJS)(_this.props.schema);
56 var nextPropsErrors = (0, _immutable.fromJS)(nextProps.fieldErrors);
57 var thisPropsErrors = (0, _immutable.fromJS)(_this.props.fieldErrors);
58
59 var updatedState = {};
60
61 if (!(0, _immutable.is)(nextPropsSchema, thisPropsSchema)) {
62 updatedState.fields = (0, _immutable.fromJS)(nextProps.schema);
63 }
64
65 if (!(0, _immutable.is)(nextPropsErrors, thisPropsErrors)) {
66 updatedState.fieldErrors = nextProps.fieldErrors;
67 }
68
69 if (updatedState.fields || updatedState.fieldErrors) _this.setState(updatedState);
70 };
71
72 _this.UNSAFE_componentWillMount = function () {
73 _this.setState({
74 fields: (0, _immutable.fromJS)(_this.props.schema)
75 });
76 };
77
78 _this._mapFieldErrors = function () {
79 return _this.state.fieldErrors.merge(_this.props.fieldErrors);
80 };
81
82 _this.handleSubmit = function (event) {
83 event.preventDefault();
84
85 var fieldErrors = (0, _validation.validate)(_this._formValidation, (0, _form.formSchemaToKeyVal)(_this.state.fields));
86
87 // Required to send error prop to ValidatedField component
88 _this.setState({ fieldErrors: fieldErrors });
89
90 if (fieldErrors && fieldErrors.size) {
91 _this.props.errorCallback && _this.props.errorCallback(fieldErrors);
92 } else {
93 _this.props.submitCallback && _this.props.submitCallback(event, _this.state.fields.toJS());
94 }
95 };
96
97 _this.handleChange = function (event) {
98 var name = event.target.name;
99 var val = event.target.value;
100 var option = event.target.option;
101
102 // Handle checkbox values
103 if (event.target.type === 'checkbox') {
104 val = event.target.checked;
105 }
106
107 _this.setState(function (prevState) {
108 var fields = prevState.fields.setIn([name, 'value'], val);
109
110 if (option) {
111 fields = fields.setIn([name, 'option'], option);
112 }
113
114 var fieldErrors = _this._mapFieldErrors().set(name, '');
115
116 return { fields: fields, fieldErrors: fieldErrors };
117 }, function () {
118 if (_this.props.changeCallback) {
119 _this.props.changeCallback(_this.state.fields.toJS(), _this.props.fieldErrors.merge(_this.state.fieldErrors));
120 }
121 });
122 };
123
124 _this.getElements = function (children, recursiveCall) {
125 // Reset validation each time this called on the form group
126 if (!recursiveCall) {
127 _this._formValidation = (0, _immutable.Map)();
128 }
129 var fieldErrors = _this._mapFieldErrors();
130
131 return _react2.default.Children.map(children, function (child) {
132 if (!child) return child;
133
134 var childProps = {};
135
136 if (child.props) {
137 var name = child.props.name;
138
139 var error = fieldErrors.get(name);
140 var value = _this.state.fields.getIn([name, 'value']);
141 var valueIsImmutable = _immutable.Iterable.isIterable(value);
142 var valueProp = valueIsImmutable ? value.toJS() : value;
143
144 if (child.props.validation) {
145 _this._formValidation = _this._formValidation.set(name, (0, _immutable.Map)({
146 validators: (0, _immutable.fromJS)(child.props.validation)
147 }));
148 }
149
150 if (_this.state.fields.has(name) && _react2.default.isValidElement(child)) {
151 childProps = {
152 changeCallback: _this.props.debounceTime ? _this.debounce : _this.handleChange,
153 value: valueProp,
154 error: error
155 };
156 }
157
158 childProps.children = _this.getElements(child.props.children, true);
159 return _react2.default.cloneElement(child, childProps);
160 }
161
162 return child;
163 });
164 };
165
166 _this.renderForm = function () {
167 var elements = _this.getElements(_this.props.children);
168 var formGroupClass = (0, _OptClass2.default)(_style2.default, 'form-group', _this.props.optClass);
169 var formWrapper = void 0;
170
171 if (!_this.props.nested) {
172 formWrapper = _react2.default.createElement(
173 'form',
174 { className: formGroupClass, onSubmit: _this.handleSubmit },
175 _react2.default.createElement(
176 'fieldset',
177 { className: _style2.default.fieldset },
178 elements
179 )
180 );
181 } else {
182 var fieldsetClass = (0, _OptClass2.default)(_style2.default, 'fieldset', _this.props.optClass);
183
184 formWrapper = _react2.default.createElement(
185 'fieldset',
186 { className: fieldsetClass },
187 elements
188 );
189 }
190 return formWrapper;
191 };
192
193 _this.render = function () {
194 return _this.renderForm();
195 };
196
197 _this.debounce = (0, _debounce2.default)(_this.handleChange, _this.props.debounceTime);
198 _this._formValidation = null;
199 return _this;
200 }
201
202 // Errors can be passed in via props if external validation is used or
203 // they can be captured from state if internal validation is used
204
205
206 return FormGroup;
207}(_react2.default.Component);
208
209FormGroup.propTypes = {
210 /**
211 * A configuration object of name/value pairs
212 * that correspond to the form fields names.
213 */
214 schema: _propTypes2.default.object,
215 /**
216 * A callback function to be called when a form value changes.
217 */
218 changeCallback: _propTypes2.default.func,
219 /**
220 * A callback function to be called when the form has error(s).
221 */
222 errorCallback: _propTypes2.default.func,
223 /**
224 * A callback function to be called when the form is submitted.
225 */
226 submitCallback: _propTypes2.default.func,
227 /**
228 * Optional CSS class(es) to be used for local styles (string or array of strings)
229 */
230 optClass: _propTypes2.default.oneOfType([_propTypes2.default.array, _propTypes2.default.string]),
231 /**
232 * Option to turn off form wrapper (for nested components)
233 */
234 nested: _propTypes2.default.bool,
235 /**
236 * Option to turn off debounce when something in the form group changes
237 */
238 debounceTime: _propTypes2.default.number,
239 /**
240 * A key value pair eg: { 'message': 'this is an error message' }, were the
241 * key repesents the `name` of the given field to validate
242 */
243 fieldErrors: _propTypes2.default.object
244};
245FormGroup.defaultProps = {
246 debounceTime: 0,
247 fieldErrors: (0, _immutable.Map)()
248};
249exports.default = FormGroup;
\No newline at end of file