UNPKG

19.6 kBJavaScriptView Raw
1'use strict';
2
3exports.__esModule = true;
4exports.default = undefined;
5
6var _typeof2 = require('babel-runtime/helpers/typeof');
7
8var _typeof3 = _interopRequireDefault(_typeof2);
9
10var _extends2 = require('babel-runtime/helpers/extends');
11
12var _extends3 = _interopRequireDefault(_extends2);
13
14var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
15
16var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
17
18var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
19
20var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
21
22var _inherits2 = require('babel-runtime/helpers/inherits');
23
24var _inherits3 = _interopRequireDefault(_inherits2);
25
26var _class, _temp;
27
28var _react = require('react');
29
30var _react2 = _interopRequireDefault(_react);
31
32var _propTypes = require('prop-types');
33
34var _propTypes2 = _interopRequireDefault(_propTypes);
35
36var _classnames = require('classnames');
37
38var _classnames2 = _interopRequireDefault(_classnames);
39
40var _grid = require('../grid');
41
42var _grid2 = _interopRequireDefault(_grid);
43
44var _responsiveGrid = require('../responsive-grid');
45
46var _responsiveGrid2 = _interopRequireDefault(_responsiveGrid);
47
48var _util = require('../util');
49
50var _error = require('./error');
51
52var _error2 = _interopRequireDefault(_error);
53
54var _enhance = require('./enhance');
55
56function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
57
58var Row = _grid2.default.Row,
59 Col = _grid2.default.Col;
60var Cell = _responsiveGrid2.default.Cell;
61var isNil = _util.obj.isNil;
62
63/** Form.Item
64 * @description 手动传递了 wrapCol labelCol 会使用 Grid 辅助布局; labelAlign='top' 会强制禁用 Grid
65 * @order 1
66 */
67
68var Item = (_temp = _class = function (_React$Component) {
69 (0, _inherits3.default)(Item, _React$Component);
70
71 function Item() {
72 (0, _classCallCheck3.default)(this, Item);
73 return (0, _possibleConstructorReturn3.default)(this, _React$Component.apply(this, arguments));
74 }
75
76 /**
77 * 从子元素里面提取表单组件. TODO: 2.x 中改为只获取一个元素
78 */
79 Item.prototype.getNames = function getNames(children) {
80 var name = this.props.name;
81
82 var childrenList = _react2.default.Children.toArray(children);
83 var nameList = childrenList.filter(function (c) {
84 return c.props && ('name' in c.props || 'data-meta' in c.props);
85 }).map(function (c) {
86 return c.props.name || c.props.id;
87 });
88
89 if (nameList.length) {
90 return nameList;
91 } else if (name) {
92 return [name];
93 }
94
95 return [];
96 };
97
98 Item.prototype.getHelper = function getHelper(children) {
99 var help = this.props.help;
100 var _formField = this.context._formField;
101
102 return _react2.default.createElement(
103 _error2.default,
104 { name: help === undefined ? this.getNames(children) : undefined, field: _formField },
105 help
106 );
107 };
108
109 Item.prototype.getState = function getState(children) {
110 var validateState = this.props.validateState;
111
112 if (validateState) {
113 return validateState;
114 }
115
116 if (this.context._formField) {
117 var getState = this.context._formField.getState;
118
119 var names = this.getNames(children);
120 if (!names.length) {
121 return '';
122 }
123
124 // get first name
125 return getState(names[0]);
126 }
127
128 return undefined;
129 };
130
131 Item.prototype.getSize = function getSize() {
132 return this.props.size || this.context._formSize;
133 };
134
135 Item.prototype.getDisabled = function getDisabled() {
136 return 'disabled' in this.props ? this.props.disabled : this.context._formDisabled;
137 };
138
139 Item.prototype.getIsPreview = function getIsPreview() {
140 return 'isPreview' in this.props ? this.props.isPreview : this.context._formPreview;
141 };
142
143 Item.prototype.getFullWidth = function getFullWidth() {
144 return isNil(this.props.fullWidth) ? !!this.context._formFullWidth : this.props.fullWidth;
145 };
146
147 Item.prototype.getLabelForErrorMessage = function getLabelForErrorMessage() {
148 var label = this.props.label;
149
150 if (!label || typeof label !== 'string') {
151 return null;
152 }
153
154 label = label.replace(':', '').replace(':', '');
155
156 var labelForErrorMessage = 'useLabelForErrorMessage' in this.props ? this.props.useLabelForErrorMessage : this.context._formLabelForErrorMessage;
157 if (labelForErrorMessage && label) {
158 return label;
159 }
160
161 return null;
162 };
163
164 Item.prototype.getItemLabel = function getItemLabel(children) {
165 var _classNames;
166
167 var _props = this.props,
168 id = _props.id,
169 required = _props.required,
170 _props$asterisk = _props.asterisk,
171 asterisk = _props$asterisk === undefined ? required : _props$asterisk,
172 label = _props.label,
173 labelCol = _props.labelCol,
174 wrapperCol = _props.wrapperCol,
175 prefix = _props.prefix,
176 responsive = _props.responsive,
177 labelWidth = _props.labelWidth,
178 labelTextAlign = _props.labelTextAlign,
179 colon = _props.colon;
180
181
182 var labelAlign = this.getLabelAlign(this.props.labelAlign, this.props.device);
183
184 if (!label) {
185 return null;
186 }
187
188 var ele = _react2.default.createElement(
189 'label',
190 { htmlFor: id || this.getNames(children)[0], required: asterisk, key: 'label' },
191 label
192 );
193
194 var cls = (0, _classnames2.default)((_classNames = {}, _classNames[prefix + 'form-item-label'] = true, _classNames['has-colon'] = colon, _classNames[prefix + 'left'] = labelTextAlign === 'left', _classNames));
195
196 if (responsive && labelWidth && labelAlign !== 'top') {
197 return _react2.default.createElement(
198 'div',
199 { className: cls, style: { width: labelWidth } },
200 ele
201 );
202 }
203
204 if ((wrapperCol || labelCol) && labelAlign !== 'top') {
205 return _react2.default.createElement(
206 Col,
207 (0, _extends3.default)({}, labelCol, { className: cls }),
208 ele
209 );
210 }
211
212 return _react2.default.createElement(
213 'div',
214 { className: cls },
215 ele
216 );
217 };
218
219 Item.prototype.getItemWrapper = function getItemWrapper(children) {
220 var _this2 = this;
221
222 var _props2 = this.props,
223 hasFeedback = _props2.hasFeedback,
224 labelCol = _props2.labelCol,
225 wrapperCol = _props2.wrapperCol,
226 extra = _props2.extra,
227 prefix = _props2.prefix,
228 renderPreview = _props2.renderPreview,
229 name = _props2.name;
230
231
232 var labelAlign = this.getLabelAlign(this.props.labelAlign, this.props.device);
233
234 var state = this.getState(children);
235
236 var isPreview = this.getIsPreview();
237 var childrenProps = {
238 size: this.getSize()
239 };
240
241 if (isPreview) {
242 childrenProps.isPreview = true;
243 }
244
245 if ('renderPreview' in this.props && typeof renderPreview === 'function') {
246 childrenProps.renderPreview = renderPreview;
247 }
248
249 if (state && (state === 'error' || hasFeedback)) {
250 childrenProps.state = state;
251 }
252
253 if (labelAlign === 'inset') {
254 childrenProps.label = this.getItemLabel(children);
255 }
256
257 if (this.getDisabled()) {
258 childrenProps.disabled = true;
259 }
260
261 var labelForErrorMessage = this.getLabelForErrorMessage();
262
263 var ele = _react2.default.Children.map(children, function (child, idx) {
264 if (child && ['function', 'object'].indexOf((0, _typeof3.default)(child.type)) > -1 && child.type._typeMark !== 'form_item' && child.type._typeMark !== 'form_error') {
265 var extraProps = childrenProps;
266 // 自己直接使用 field.init 会在 props 上面留下 data-meta
267 // name 挪到 FormItem 上面,默认把第一个元素当做 Form 组件
268 if (_this2.context._formField && !('data-meta' in child.props) && ('name' in child.props || name && idx === 0) //TODO:1.x 为了不BR, 2.x 中把优先级调换下,优先取 FormItem 的 name
269 ) {
270 var initName = 'name' in child.props && child.props.name ? child.props.name : name;
271 extraProps = _this2.context._formField.init(initName, (0, _extends3.default)({}, (0, _enhance.getFieldInitCfg)(_this2.props, child.type.displayName, labelForErrorMessage), {
272 props: (0, _extends3.default)({}, child.props, { ref: child.ref })
273 }), childrenProps);
274 } else {
275 extraProps = (0, _extends3.default)({}, child.props, extraProps);
276 }
277
278 return _react2.default.cloneElement(child, extraProps);
279 }
280
281 return child;
282 });
283
284 var help = this.getHelper(children);
285
286 if ((wrapperCol || labelCol) && labelAlign !== 'top') {
287 return _react2.default.createElement(
288 Col,
289 (0, _extends3.default)({}, wrapperCol, { className: prefix + 'form-item-control', key: 'item' }),
290 ele,
291 ' ',
292 help,
293 ' ',
294 extra
295 );
296 }
297
298 return _react2.default.createElement(
299 'div',
300 { className: prefix + 'form-item-control' },
301 ele,
302 ' ',
303 help,
304 ' ',
305 extra
306 );
307 };
308
309 Item.prototype.getLabelAlign = function getLabelAlign(labelAlign, device) {
310 if (device === 'phone') {
311 return 'top';
312 }
313
314 return labelAlign;
315 };
316
317 Item.prototype.render = function render() {
318 var _classNames2;
319
320 var _props3 = this.props,
321 className = _props3.className,
322 style = _props3.style,
323 prefix = _props3.prefix,
324 wrapperCol = _props3.wrapperCol,
325 labelCol = _props3.labelCol,
326 responsive = _props3.responsive,
327 children = _props3.children;
328
329
330 var labelAlign = this.getLabelAlign(this.props.labelAlign, this.props.device);
331
332 var childrenNode = children;
333 if (typeof children === 'function' && this.context._formField) {
334 childrenNode = children(this.context._formField.getValues());
335 }
336
337 var state = this.getState(childrenNode);
338 var size = this.getSize();
339 var fullWidth = this.getFullWidth();
340 var isPreview = this.getIsPreview();
341
342 var itemClassName = (0, _classnames2.default)((_classNames2 = {}, _classNames2[prefix + 'form-item'] = true, _classNames2['' + prefix + labelAlign] = labelAlign, _classNames2['has-' + state] = !!state, _classNames2['' + prefix + size] = !!size, _classNames2[prefix + 'form-item-fullwidth'] = fullWidth, _classNames2['' + className] = !!className, _classNames2[prefix + 'form-preview'] = isPreview, _classNames2));
343
344 // 垂直模式并且左对齐才用到
345 var Tag = responsive ? Cell : (wrapperCol || labelCol) && labelAlign !== 'top' ? Row : 'div';
346 var label = labelAlign === 'inset' ? null : this.getItemLabel(childrenNode);
347
348 return _react2.default.createElement(
349 Tag,
350 (0, _extends3.default)({}, _util.obj.pickOthers(Item.propTypes, this.props), { className: itemClassName, style: style }),
351 label,
352 this.getItemWrapper(childrenNode)
353 );
354 };
355
356 return Item;
357}(_react2.default.Component), _class.propTypes = {
358 /**
359 * 样式前缀
360 */
361 prefix: _propTypes2.default.string,
362 rtl: _propTypes2.default.bool,
363 /**
364 * label 标签的文本
365 */
366 label: _propTypes2.default.node,
367 /**
368 * label 标签布局,通 `<Col>` 组件,设置 span offset 值,如 {span: 8, offset: 16},该项仅在垂直表单有效
369 */
370 labelCol: _propTypes2.default.object,
371 /**
372 * 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol
373 */
374 wrapperCol: _propTypes2.default.object,
375 /**
376 * 自定义提示信息,如不设置,则会根据校验规则自动生成.
377 */
378 help: _propTypes2.default.node,
379 /**
380 * 字段名,默认赋值给第一个子元素
381 */
382 name: _propTypes2.default.string,
383 /**
384 * 额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 位于错误信息后面
385 */
386 extra: _propTypes2.default.node,
387 /**
388 * 校验状态,如不设置,则会根据校验规则自动生成
389 * @enumdesc 失败, 成功, 校验中, 警告
390 */
391 validateState: _propTypes2.default.oneOf(['error', 'success', 'loading', 'warning']),
392 /**
393 * 配合 validateState 属性使用,是否展示 success/loading 的校验状态图标, 目前只有Input支持
394 */
395 hasFeedback: _propTypes2.default.bool, //TODO: hasFeedback => validateStatus=[error,success,loading]
396 /**
397 * 自定义内联样式
398 */
399 style: _propTypes2.default.object,
400 id: _propTypes2.default.string,
401 /**
402 * node 或者 function(values)
403 */
404 children: _propTypes2.default.oneOfType([_propTypes2.default.node, _propTypes2.default.func]),
405 /**
406 * 单个 Item 的 size 自定义,优先级高于 Form 的 size, 并且当组件与 Item 一起使用时,组件自身设置 size 属性无效。
407 */
408 size: _propTypes2.default.oneOf(['large', 'small', 'medium']),
409 /**
410 * 单个 Item 中表单类组件宽度是否是100%
411 */
412 fullWidth: _propTypes2.default.bool,
413 /**
414 * 标签的位置, 如果不设置 labelCol 和 wrapperCol 那么默认是标签在上
415 * @enumdesc 上, 左, 内
416 */
417 labelAlign: _propTypes2.default.oneOf(['top', 'left', 'inset']),
418 /**
419 * 标签的左右对齐方式
420 * @enumdesc 左, 右
421 */
422 labelTextAlign: _propTypes2.default.oneOf(['left', 'right']),
423 /**
424 * 扩展class
425 */
426 className: _propTypes2.default.string,
427 /**
428 * [表单校验] 不能为空
429 */
430 required: _propTypes2.default.bool,
431 /**
432 * required 的星号是否显示
433 */
434 asterisk: _propTypes2.default.bool,
435 /**
436 * required 自定义错误信息
437 */
438 requiredMessage: _propTypes2.default.string,
439 /**
440 * required 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
441 */
442 requiredTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
443 /**
444 * [表单校验] 最小值
445 */
446 min: _propTypes2.default.number,
447 /**
448 * [表单校验] 最大值
449 */
450 max: _propTypes2.default.number,
451 /**
452 * min/max 自定义错误信息
453 */
454 minmaxMessage: _propTypes2.default.string,
455 /**
456 * min/max 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
457 */
458 minmaxTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
459 /**
460 * [表单校验] 字符串最小长度 / 数组最小个数
461 */
462 minLength: _propTypes2.default.number,
463 /**
464 * [表单校验] 字符串最大长度 / 数组最大个数
465 */
466 maxLength: _propTypes2.default.number,
467 /**
468 * minLength/maxLength 自定义错误信息
469 */
470 minmaxLengthMessage: _propTypes2.default.string,
471 /**
472 * minLength/maxLength 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
473 */
474 minmaxLengthTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
475 /**
476 * [表单校验] 字符串精确长度 / 数组精确个数
477 */
478 length: _propTypes2.default.number,
479 /**
480 * length 自定义错误信息
481 */
482 lengthMessage: _propTypes2.default.string,
483 /**
484 * length 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
485 */
486 lengthTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
487 /**
488 * 正则校验
489 */
490 pattern: _propTypes2.default.any,
491 /**
492 * pattern 自定义错误信息
493 */
494 patternMessage: _propTypes2.default.string,
495 /**
496 * pattern 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
497 */
498 patternTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
499 /**
500 * [表单校验] 四种常用的 pattern
501 */
502 format: _propTypes2.default.oneOf(['number', 'email', 'url', 'tel']),
503 /**
504 * format 自定义错误信息
505 */
506 formatMessage: _propTypes2.default.string,
507 /**
508 * format 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
509 */
510 formatTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
511 /**
512 * [表单校验] 自定义校验函数
513 */
514 validator: _propTypes2.default.func,
515 /**
516 * validator 校验何时触发,默认值 onChange, 原生事件均可使用 onChange/onBlur/onFocus/...
517 */
518 validatorTrigger: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.array]),
519 /**
520 * 是否修改数据时自动触发校验
521 */
522 autoValidate: _propTypes2.default.bool,
523 /**
524 * 预设屏幕宽度
525 */
526 device: _propTypes2.default.oneOf(['phone', 'tablet', 'desktop']),
527 responsive: _propTypes2.default.bool,
528 /**
529 * 在响应式布局模式下,表单项占多少列
530 */
531 colSpan: _propTypes2.default.number,
532 /**
533 * 在响应式布局下,且label在左边时,label的宽度是多少
534 */
535 labelWidth: _propTypes2.default.oneOfType([_propTypes2.default.string, _propTypes2.default.number]),
536 /**
537 * 是否开启预览态
538 */
539 isPreview: _propTypes2.default.bool,
540 /**
541 * 预览态模式下渲染的内容
542 * @param {any} value 根据包裹的组件的 value 类型而决定
543 */
544 renderPreview: _propTypes2.default.func,
545 /**
546 * 是否使用 label 替换校验信息的 name 字段
547 */
548 useLabelForErrorMessage: _propTypes2.default.bool,
549 /**
550 * 表示是否显示 label 后面的冒号
551 */
552 colon: _propTypes2.default.bool,
553 /**
554 * 是否禁用表单
555 */
556 disabled: _propTypes2.default.bool,
557 /**
558 * 子元素的 value 名称
559 */
560 valueName: _propTypes2.default.string
561}, _class.defaultProps = {
562 prefix: 'next-',
563 hasFeedback: false,
564 labelWidth: 100
565}, _class.contextTypes = {
566 _formField: _propTypes2.default.object,
567 _formSize: _propTypes2.default.oneOf(['large', 'small', 'medium']),
568 _formDisabled: _propTypes2.default.bool,
569 _formPreview: _propTypes2.default.bool,
570 _formFullWidth: _propTypes2.default.bool,
571 _formLabelForErrorMessage: _propTypes2.default.bool
572}, _class._typeMark = 'form_item', _temp);
573Item.displayName = 'Item';
574exports.default = Item;
575module.exports = exports['default'];
\No newline at end of file