1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | 'use strict';
|
10 |
|
11 | var _assign = require('object-assign');
|
12 |
|
13 | var LinkedValueUtils = require('./LinkedValueUtils');
|
14 | var ReactDOMComponentTree = require('./ReactDOMComponentTree');
|
15 | var ReactUpdates = require('./ReactUpdates');
|
16 |
|
17 | var warning = require('fbjs/lib/warning');
|
18 |
|
19 | var didWarnValueLink = false;
|
20 | var didWarnValueDefaultValue = false;
|
21 |
|
22 | function updateOptionsIfPendingUpdateAndMounted() {
|
23 | if (this._rootNodeID && this._wrapperState.pendingUpdate) {
|
24 | this._wrapperState.pendingUpdate = false;
|
25 |
|
26 | var props = this._currentElement.props;
|
27 | var value = LinkedValueUtils.getValue(props);
|
28 |
|
29 | if (value != null) {
|
30 | updateOptions(this, Boolean(props.multiple), value);
|
31 | }
|
32 | }
|
33 | }
|
34 |
|
35 | function getDeclarationErrorAddendum(owner) {
|
36 | if (owner) {
|
37 | var name = owner.getName();
|
38 | if (name) {
|
39 | return ' Check the render method of `' + name + '`.';
|
40 | }
|
41 | }
|
42 | return '';
|
43 | }
|
44 |
|
45 | var valuePropNames = ['value', 'defaultValue'];
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | function checkSelectPropTypes(inst, props) {
|
52 | var owner = inst._currentElement._owner;
|
53 | LinkedValueUtils.checkPropTypes('select', props, owner);
|
54 |
|
55 | if (props.valueLink !== undefined && !didWarnValueLink) {
|
56 | process.env.NODE_ENV !== 'production' ? warning(false, '`valueLink` prop on `select` is deprecated; set `value` and `onChange` instead.') : void 0;
|
57 | didWarnValueLink = true;
|
58 | }
|
59 |
|
60 | for (var i = 0; i < valuePropNames.length; i++) {
|
61 | var propName = valuePropNames[i];
|
62 | if (props[propName] == null) {
|
63 | continue;
|
64 | }
|
65 | var isArray = Array.isArray(props[propName]);
|
66 | if (props.multiple && !isArray) {
|
67 | process.env.NODE_ENV !== 'production' ? warning(false, 'The `%s` prop supplied to <select> must be an array if ' + '`multiple` is true.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
|
68 | } else if (!props.multiple && isArray) {
|
69 | process.env.NODE_ENV !== 'production' ? warning(false, 'The `%s` prop supplied to <select> must be a scalar ' + 'value if `multiple` is false.%s', propName, getDeclarationErrorAddendum(owner)) : void 0;
|
70 | }
|
71 | }
|
72 | }
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 |
|
80 | function updateOptions(inst, multiple, propValue) {
|
81 | var selectedValue, i;
|
82 | var options = ReactDOMComponentTree.getNodeFromInstance(inst).options;
|
83 |
|
84 | if (multiple) {
|
85 | selectedValue = {};
|
86 | for (i = 0; i < propValue.length; i++) {
|
87 | selectedValue['' + propValue[i]] = true;
|
88 | }
|
89 | for (i = 0; i < options.length; i++) {
|
90 | var selected = selectedValue.hasOwnProperty(options[i].value);
|
91 | if (options[i].selected !== selected) {
|
92 | options[i].selected = selected;
|
93 | }
|
94 | }
|
95 | } else {
|
96 |
|
97 |
|
98 | selectedValue = '' + propValue;
|
99 | for (i = 0; i < options.length; i++) {
|
100 | if (options[i].value === selectedValue) {
|
101 | options[i].selected = true;
|
102 | return;
|
103 | }
|
104 | }
|
105 | if (options.length) {
|
106 | options[0].selected = true;
|
107 | }
|
108 | }
|
109 | }
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 |
|
126 | var ReactDOMSelect = {
|
127 | getHostProps: function (inst, props) {
|
128 | return _assign({}, props, {
|
129 | onChange: inst._wrapperState.onChange,
|
130 | value: undefined
|
131 | });
|
132 | },
|
133 |
|
134 | mountWrapper: function (inst, props) {
|
135 | if (process.env.NODE_ENV !== 'production') {
|
136 | checkSelectPropTypes(inst, props);
|
137 | }
|
138 |
|
139 | var value = LinkedValueUtils.getValue(props);
|
140 | inst._wrapperState = {
|
141 | pendingUpdate: false,
|
142 | initialValue: value != null ? value : props.defaultValue,
|
143 | listeners: null,
|
144 | onChange: _handleChange.bind(inst),
|
145 | wasMultiple: Boolean(props.multiple)
|
146 | };
|
147 |
|
148 | if (props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue) {
|
149 | process.env.NODE_ENV !== 'production' ? warning(false, 'Select elements must be either controlled or uncontrolled ' + '(specify either the value prop, or the defaultValue prop, but not ' + 'both). Decide between using a controlled or uncontrolled select ' + 'element and remove one of these props. More info: ' + 'https://fb.me/react-controlled-components') : void 0;
|
150 | didWarnValueDefaultValue = true;
|
151 | }
|
152 | },
|
153 |
|
154 | getSelectValueContext: function (inst) {
|
155 |
|
156 |
|
157 | return inst._wrapperState.initialValue;
|
158 | },
|
159 |
|
160 | postUpdateWrapper: function (inst) {
|
161 | var props = inst._currentElement.props;
|
162 |
|
163 |
|
164 |
|
165 | inst._wrapperState.initialValue = undefined;
|
166 |
|
167 | var wasMultiple = inst._wrapperState.wasMultiple;
|
168 | inst._wrapperState.wasMultiple = Boolean(props.multiple);
|
169 |
|
170 | var value = LinkedValueUtils.getValue(props);
|
171 | if (value != null) {
|
172 | inst._wrapperState.pendingUpdate = false;
|
173 | updateOptions(inst, Boolean(props.multiple), value);
|
174 | } else if (wasMultiple !== Boolean(props.multiple)) {
|
175 |
|
176 | if (props.defaultValue != null) {
|
177 | updateOptions(inst, Boolean(props.multiple), props.defaultValue);
|
178 | } else {
|
179 |
|
180 | updateOptions(inst, Boolean(props.multiple), props.multiple ? [] : '');
|
181 | }
|
182 | }
|
183 | }
|
184 | };
|
185 |
|
186 | function _handleChange(event) {
|
187 | var props = this._currentElement.props;
|
188 | var returnValue = LinkedValueUtils.executeOnChange(props, event);
|
189 |
|
190 | if (this._rootNodeID) {
|
191 | this._wrapperState.pendingUpdate = true;
|
192 | }
|
193 | ReactUpdates.asap(updateOptionsIfPendingUpdateAndMounted, this);
|
194 | return returnValue;
|
195 | }
|
196 |
|
197 | module.exports = ReactDOMSelect; |
\ | No newline at end of file |