@samitouri / QOS-React / commits / 8af6f9e5a2

Fix <input> with type date/time/etc. issue on mobile browsers (#7397)

Fix <input> with type date/time/etc. issue on mobile browsers

Keyan Zhang committed Aug 2, 2016 at 12:56 UTC 8af6f9e5a2f74256b6dc955bbc8be3d90435151e
2 files changed +73 -2
src/renderers/dom/client/wrappers/ReactDOMInput.js
+20 -2
@@ -230,8 +230,26 @@ var ReactDOMInput = {
230 // are not resetable nodes so this operation doesn't matter and actually
231 // removes browser-default values (eg "Submit Query") when no value is
232 // provided.
233 - if (props.type !== 'submit' && props.type !== 'reset') {
234 - node.value = node.value;
233 +
234 + switch (props.type) {
235 + case 'submit':
236 + case 'reset':
237 + break;
238 + case 'color':
239 + case 'date':
240 + case 'datetime':
241 + case 'datetime-local':
242 + case 'month':
243 + case 'time':
244 + case 'week':
245 + // This fixes the no-show issue on iOS Safari and Android Chrome:
246 + // https://github.com/facebook/react/issues/7233
247 + node.value = '';
248 + node.value = node.defaultValue;
249 + break;
250 + default:
251 + node.value = node.value;
252 + break;
253 }
254
255 // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js
+53
@@ -82,6 +82,21 @@ describe('ReactDOMInput', function() {
82 expect(node.defaultValue).toBe('1');
83 });
84
85 + it('should update `defaultValue` for uncontrolled date/time input', function() {
86 + var container = document.createElement('div');
87 +
88 + var node = ReactDOM.render(<input type="date" defaultValue="1980-01-01" />, container);
89 +
90 + expect(node.value).toBe('1980-01-01');
91 +
92 + ReactDOM.render(<input type="date" defaultValue="2000-01-01" />, container);
93 +
94 + expect(node.value).toBe('1980-01-01');
95 + expect(node.defaultValue).toBe('2000-01-01');
96 +
97 + ReactDOM.render(<input type="date" />, container);
98 + });
99 +
100 it('should take `defaultValue` when changing to uncontrolled input', function() {
101 var container = document.createElement('div');
102
@@ -790,4 +805,42 @@ describe('ReactDOMInput', function() {
805 expect(node.value).toEqual('Test');
806 });
807
808 + it('resets value of date/time input to fix bugs in iOS Safari', function() {
809 + // https://github.com/facebook/react/issues/7233
810 + if (!ReactDOMFeatureFlags.useCreateElement) {
811 + return;
812 + }
813 +
814 + function strify(x) {
815 + return JSON.stringify(x, null, 2);
816 + }
817 +
818 + var log = [];
819 + var originalCreateElement = document.createElement;
820 + spyOn(document, 'createElement').and.callFake(function(type) {
821 + var el = originalCreateElement.apply(this, arguments);
822 + if (type === 'input') {
823 + Object.defineProperty(el, 'value', {
824 + set: function(val) {
825 + log.push(`node.value = ${strify(val)}`);
826 + },
827 + });
828 + spyOn(el, 'setAttribute').and.callFake(function(name, val) {
829 + log.push(`node.setAttribute(${strify(name)}, ${strify(val)})`);
830 + });
831 + }
832 + return el;
833 + });
834 +
835 + ReactTestUtils.renderIntoDocument(<input type="date" defaultValue="1980-01-01" />);
836 + expect(log).toEqual([
837 + 'node.setAttribute("data-reactroot", "")',
838 + 'node.setAttribute("type", "date")',
839 + 'node.setAttribute("value", "1980-01-01")',
840 + 'node.value = ""',
841 + 'node.value = ""',
842 + 'node.setAttribute("checked", "")',
843 + 'node.setAttribute("checked", "")',
844 + ]);
845 + });
846 });