UNPKG

3.56 kBJavaScriptView Raw
1/**
2 * Copyright (c) 2013-present, Facebook, Inc.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9'use strict';
10
11var _assign = require('object-assign');
12
13var React = require('react/lib/React');
14var ReactDOMComponentTree = require('./ReactDOMComponentTree');
15var ReactDOMSelect = require('./ReactDOMSelect');
16
17var warning = require('fbjs/lib/warning');
18var didWarnInvalidOptionChildren = false;
19
20function flattenChildren(children) {
21 var content = '';
22
23 // Flatten children and warn if they aren't strings or numbers;
24 // invalid types are ignored.
25 React.Children.forEach(children, function (child) {
26 if (child == null) {
27 return;
28 }
29 if (typeof child === 'string' || typeof child === 'number') {
30 content += child;
31 } else if (!didWarnInvalidOptionChildren) {
32 didWarnInvalidOptionChildren = true;
33 process.env.NODE_ENV !== 'production' ? warning(false, 'Only strings and numbers are supported as <option> children.') : void 0;
34 }
35 });
36
37 return content;
38}
39
40/**
41 * Implements an <option> host component that warns when `selected` is set.
42 */
43var ReactDOMOption = {
44 mountWrapper: function (inst, props, hostParent) {
45 // TODO (yungsters): Remove support for `selected` in <option>.
46 if (process.env.NODE_ENV !== 'production') {
47 process.env.NODE_ENV !== 'production' ? warning(props.selected == null, 'Use the `defaultValue` or `value` props on <select> instead of ' + 'setting `selected` on <option>.') : void 0;
48 }
49
50 // Look up whether this option is 'selected'
51 var selectValue = null;
52 if (hostParent != null) {
53 var selectParent = hostParent;
54
55 if (selectParent._tag === 'optgroup') {
56 selectParent = selectParent._hostParent;
57 }
58
59 if (selectParent != null && selectParent._tag === 'select') {
60 selectValue = ReactDOMSelect.getSelectValueContext(selectParent);
61 }
62 }
63
64 // If the value is null (e.g., no specified value or after initial mount)
65 // or missing (e.g., for <datalist>), we don't change props.selected
66 var selected = null;
67 if (selectValue != null) {
68 var value;
69 if (props.value != null) {
70 value = props.value + '';
71 } else {
72 value = flattenChildren(props.children);
73 }
74 selected = false;
75 if (Array.isArray(selectValue)) {
76 // multiple
77 for (var i = 0; i < selectValue.length; i++) {
78 if ('' + selectValue[i] === value) {
79 selected = true;
80 break;
81 }
82 }
83 } else {
84 selected = '' + selectValue === value;
85 }
86 }
87
88 inst._wrapperState = { selected: selected };
89 },
90
91 postMountWrapper: function (inst) {
92 // value="" should make a value attribute (#6219)
93 var props = inst._currentElement.props;
94 if (props.value != null) {
95 var node = ReactDOMComponentTree.getNodeFromInstance(inst);
96 node.setAttribute('value', props.value);
97 }
98 },
99
100 getHostProps: function (inst, props) {
101 var hostProps = _assign({ selected: undefined, children: undefined }, props);
102
103 // Read state only from initial mount because <select> updates value
104 // manually; we need the initial state only for server rendering
105 if (inst._wrapperState.selected != null) {
106 hostProps.selected = inst._wrapperState.selected;
107 }
108
109 var content = flattenChildren(props.children);
110
111 if (content) {
112 hostProps.children = content;
113 }
114
115 return hostProps;
116 }
117};
118
119module.exports = ReactDOMOption;
\No newline at end of file