@samitouri / QOS-React / commits / 904ee9a678

allow to ignore value attribute for option (#5362)

yiminghe committed May 10, 2016 at 00:22 UTC 904ee9a6787d74fcffcbf1ceece1c69a9014604d
2 files changed +58 -32
src/renderers/dom/client/wrappers/ReactDOMOption.js
+33 -19
@@ -16,6 +16,30 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree');
16 var ReactDOMSelect = require('ReactDOMSelect');
17
18 var warning = require('warning');
19 +var didWarnInvalidOptionChildren = false;
20 +
21 +function flattenChildren(children) {
22 + var content = '';
23 +
24 + // Flatten children and warn if they aren't strings or numbers;
25 + // invalid types are ignored.
26 + ReactChildren.forEach(children, function(child) {
27 + if (child == null) {
28 + return;
29 + }
30 + if (typeof child === 'string' || typeof child === 'number') {
31 + content += child;
32 + } else if (!didWarnInvalidOptionChildren) {
33 + didWarnInvalidOptionChildren = true;
34 + warning(
35 + false,
36 + 'Only strings and numbers are supported as <option> children.'
37 + );
38 + }
39 + });
40 +
41 + return content;
42 +}
43
44 /**
45 * Implements an <option> native component that warns when `selected` is set.
@@ -49,17 +73,23 @@ var ReactDOMOption = {
73 // or missing (e.g., for <datalist>), we don't change props.selected
74 var selected = null;
75 if (selectValue != null) {
76 + var value;
77 + if (props.value != null) {
78 + value = props.value + '';
79 + } else {
80 + value = flattenChildren(props.children);
81 + }
82 selected = false;
83 if (Array.isArray(selectValue)) {
84 // multiple
85 for (var i = 0; i < selectValue.length; i++) {
56 - if ('' + selectValue[i] === '' + props.value) {
86 + if ('' + selectValue[i] === value) {
87 selected = true;
88 break;
89 }
90 }
91 } else {
62 - selected = ('' + selectValue === '' + props.value);
92 + selected = ('' + selectValue === value);
93 }
94 }
95
@@ -84,23 +114,7 @@ var ReactDOMOption = {
114 nativeProps.selected = inst._wrapperState.selected;
115 }
116
87 - var content = '';
88 -
89 - // Flatten children and warn if they aren't strings or numbers;
90 - // invalid types are ignored.
91 - ReactChildren.forEach(props.children, function(child) {
92 - if (child == null) {
93 - return;
94 - }
95 - if (typeof child === 'string' || typeof child === 'number') {
96 - content += child;
97 - } else {
98 - warning(
99 - false,
100 - 'Only strings and numbers are supported as <option> children.'
101 - );
102 - }
103 - });
117 + var content = flattenChildren(props.children);
118
119 if (content) {
120 nativeProps.children = content;
src/renderers/dom/client/wrappers/__tests__/ReactDOMOption-test.js
+25 -13
@@ -31,28 +31,18 @@ describe('ReactDOMOption', function() {
31 expect(node.innerHTML).toBe('1 foo');
32 });
33
34 - it('should ignore invalid children types', function() {
34 + it('should ignore and warn invalid children types', function() {
35 spyOn(console, 'error');
36 var stub = <option>{1} <div /> {2}</option>;
37 stub = ReactTestUtils.renderIntoDocument(stub);
38 var node = ReactDOM.findDOMNode(stub);
39 -
39 expect(node.innerHTML).toBe('1 2');
40 + ReactTestUtils.renderIntoDocument(<option>{1} <div /> {2}</option>);
41 + // only warn once
42 expect(console.error.calls.length).toBe(1);
43 expect(console.error.argsForCall[0][0]).toContain('Only strings and numbers are supported as <option> children.');
44 });
45
45 - it('should warn when passing invalid children', function() {
46 - var stub = <option>{1} <div /></option>;
47 - spyOn(console, 'error');
48 - stub = ReactTestUtils.renderIntoDocument(stub);
49 -
50 - expect(console.error.calls.length).toBe(1);
51 - expect(console.error.argsForCall[0][0]).toContain(
52 - 'Only strings and numbers are supported as <option> children.'
53 - );
54 - });
55 -
46 it('should ignore null/undefined/false children without warning', function() {
47 var stub = <option>{1} {false}{true}{null}{undefined} {2}</option>;
48 spyOn(console, 'error');
@@ -82,4 +72,26 @@ describe('ReactDOMOption', function() {
72 expect(option.hasAttribute('value')).toBe(true);
73 expect(option.getAttribute('value')).toBe('lava');
74 });
75 +
76 + it('should allow ignoring `value` on option', function() {
77 + var a = 'a';
78 + var stub =
79 + <select value="giraffe" onChange={() => {}}>
80 + <option>monkey</option>
81 + <option>gir{a}ffe</option>
82 + <option>gorill{a}</option>
83 + </select>;
84 + var options = stub.props.children;
85 + var container = document.createElement('div');
86 + stub = ReactDOM.render(stub, container);
87 + var node = ReactDOM.findDOMNode(stub);
88 +
89 + expect(node.selectedIndex).toBe(1);
90 +
91 + ReactDOM.render(
92 + <select value="gorilla">{options}</select>,
93 + container
94 + );
95 + expect(node.selectedIndex).toEqual(2);
96 + });
97 });