The library for web and native user interfaces.
Set textarea value when changing content
At http://jsfiddle.net/spicyj/W4QLq/, typing into the textbox would cause clicking the button to do nothing; now it should work.
Ben Alpert committed
Jun 12, 2013 at 00:14 UTC
0c6f4b3bcc8dc728f4736e53e3d81d6ae4c47cb9
4 files changed
+133
-1
src/core/ReactDOM.js
+1
@@ -115,6 +115,7 @@ var ReactDOM = objMapKeyVal({
115
table: false,
116
tbody: false,
117
td: false,
118
+ // Danger: this gets monkeypatched! See ReactDOMTextarea for more info.
119
textarea: false,
120
tfoot: false,
121
th: false,
src/core/ReactDOMTextarea.js
new
+63
@@ -0,0 +1,63 @@
1
+/**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @providesModule ReactDOMTextarea
17
+ */
18
+
19
+"use strict";
20
+
21
+var ReactCompositeComponent = require('ReactCompositeComponent');
22
+var ReactDOM = require('ReactDOM');
23
+
24
+var invariant = require('invariant');
25
+
26
+// Store a reference to the <textarea> `ReactNativeComponent`.
27
+var textarea = ReactDOM.textarea;
28
+
29
+// For quickly matching children type, to test if can be treated as content.
30
+var CONTENT_TYPES = {'string': true, 'number': true};
31
+
32
+var getTextContent = function(props) {
33
+ return props.content != null ? '' + props.content :
34
+ CONTENT_TYPES[typeof props.children] ? '' + props.children : '';
35
+};
36
+
37
+/**
38
+ * Since setting .textContent on a dirty <textarea> doesn't update its value,
39
+ * we intercept prop changes here to make sure that value is updated.
40
+ */
41
+var ReactDOMTextarea = ReactCompositeComponent.createClass({
42
+ render: function() {
43
+ invariant(
44
+ this.props.dangerouslySetInnerHTML == null,
45
+ '`dangerouslySetInnerHTML` does not make sense on textarea.'
46
+ );
47
+ invariant(
48
+ this.props.children == null || CONTENT_TYPES[typeof this.props.children],
49
+ 'When present, textarea children must be a single string or number.'
50
+ );
51
+ return this.transferPropsTo(textarea(null, this.props.children));
52
+ },
53
+
54
+ componentDidUpdate: function(prevProps, prevState, rootNode) {
55
+ var oldContent = getTextContent(prevProps);
56
+ var newContent = getTextContent(this.props);
57
+ if (oldContent !== newContent) {
58
+ rootNode.value = newContent;
59
+ }
60
+ }
61
+});
62
+
63
+module.exports = ReactDOMTextarea;
src/core/ReactDefaultInjection.js
+3
-1
@@ -20,6 +20,7 @@
20
21
var ReactDOM = require('ReactDOM');
22
var ReactDOMForm = require('ReactDOMForm');
23
+var ReactDOMTextarea = require('ReactDOMTextarea');
24
25
var DefaultEventPluginOrder = require('DefaultEventPluginOrder');
26
var EnterLeaveEventPlugin = require('EnterLeaveEventPlugin');
@@ -50,7 +51,8 @@ function inject() {
51
* dependency graph we need to inject it here.
52
*/
53
ReactDOM.injection.injectComponentClasses({
53
- form: ReactDOMForm
54
+ form: ReactDOMForm,
55
+ textarea: ReactDOMTextarea
56
});
57
}
58
src/core/__tests__/ReactDOMTextarea-test.js
new
+66
@@ -0,0 +1,66 @@
1
+/**
2
+ * Copyright 2013 Facebook, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * @jsx React.DOM
17
+ * @emails react-core
18
+ */
19
+
20
+"use strict";
21
+
22
+describe('ReactDOMTextarea', function() {
23
+ var React;
24
+ var ReactTestUtils;
25
+ var transaction;
26
+
27
+ beforeEach(function() {
28
+ React = require('React');
29
+ ReactTestUtils = require('ReactTestUtils');
30
+
31
+ var ReactReconcileTransaction = require('ReactReconcileTransaction');
32
+ transaction = new ReactReconcileTransaction();
33
+ });
34
+
35
+ it("should remove value with removed children", function() {
36
+ var stub = ReactTestUtils.renderIntoDocument(<textarea>giraffe</textarea>);
37
+
38
+ expect(stub.getDOMNode().value).toEqual('giraffe');
39
+ stub.receiveProps({ children: null }, transaction);
40
+ expect(stub.getDOMNode().value).toEqual('');
41
+ });
42
+
43
+ it("should update value with a single string child", function() {
44
+ var stub = ReactTestUtils.renderIntoDocument(<textarea>monkey</textarea>);
45
+
46
+ expect(stub.getDOMNode().value).toEqual('monkey');
47
+ stub.receiveProps({ children: 'gorilla' }, transaction);
48
+ expect(stub.getDOMNode().value).toEqual('gorilla');
49
+ });
50
+
51
+ it("should update value with a single numerical child", function() {
52
+ var stub = ReactTestUtils.renderIntoDocument(<textarea>17</textarea>);
53
+
54
+ expect(stub.getDOMNode().value).toEqual('17');
55
+ stub.receiveProps({ children: 289 }, transaction);
56
+ expect(stub.getDOMNode().value).toEqual('289');
57
+ });
58
+
59
+ it("should update value with the content property", function() {
60
+ var stub = ReactTestUtils.renderIntoDocument(<textarea content="purple" />);
61
+
62
+ expect(stub.getDOMNode().value).toEqual('purple');
63
+ stub.receiveProps({ content: 'eggplant' }, transaction);
64
+ expect(stub.getDOMNode().value).toEqual('eggplant');
65
+ });
66
+});