Skip to content

Commit

Permalink
Fix <input> with type date/time/etc. issue on mobile browsers (#7397)
Browse files Browse the repository at this point in the history
Fix <input> with type date/time/etc. issue on mobile browsers
(cherry picked from commit 8af6f9e)
  • Loading branch information
keyz authored and zpao committed Aug 12, 2016
1 parent bad1080 commit 44fa2c8
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 2 deletions.
22 changes: 20 additions & 2 deletions src/renderers/dom/client/wrappers/ReactDOMInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,26 @@ var ReactDOMInput = {
// are not resetable nodes so this operation doesn't matter and actually
// removes browser-default values (eg "Submit Query") when no value is
// provided.
if (props.type !== 'submit' && props.type !== 'reset') {
node.value = node.value;

switch (props.type) {
case 'submit':
case 'reset':
break;
case 'color':
case 'date':
case 'datetime':
case 'datetime-local':
case 'month':
case 'time':
case 'week':
// This fixes the no-show issue on iOS Safari and Android Chrome:
// https://github.com/facebook/react/issues/7233
node.value = '';
node.value = node.defaultValue;
break;
default:
node.value = node.value;
break;
}

// Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug
Expand Down
53 changes: 53 additions & 0 deletions src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ describe('ReactDOMInput', function() {
expect(node.defaultValue).toBe('1');
});

it('should update `defaultValue` for uncontrolled date/time input', function() {
var container = document.createElement('div');

var node = ReactDOM.render(<input type="date" defaultValue="1980-01-01" />, container);

expect(node.value).toBe('1980-01-01');

ReactDOM.render(<input type="date" defaultValue="2000-01-01" />, container);

expect(node.value).toBe('1980-01-01');
expect(node.defaultValue).toBe('2000-01-01');

ReactDOM.render(<input type="date" />, container);
});

it('should take `defaultValue` when changing to uncontrolled input', function() {
var container = document.createElement('div');

Expand Down Expand Up @@ -781,4 +796,42 @@ describe('ReactDOMInput', function() {
expect(node.value).toEqual('Test');
});

it('resets value of date/time input to fix bugs in iOS Safari', function() {
// https://github.com/facebook/react/issues/7233
if (!ReactDOMFeatureFlags.useCreateElement) {
return;
}

function strify(x) {
return JSON.stringify(x, null, 2);
}

var log = [];
var originalCreateElement = document.createElement;
spyOn(document, 'createElement').and.callFake(function(type) {
var el = originalCreateElement.apply(this, arguments);
if (type === 'input') {
Object.defineProperty(el, 'value', {
set: function(val) {
log.push(`node.value = ${strify(val)}`);
},
});
spyOn(el, 'setAttribute').and.callFake(function(name, val) {
log.push(`node.setAttribute(${strify(name)}, ${strify(val)})`);
});
}
return el;
});

ReactTestUtils.renderIntoDocument(<input type="date" defaultValue="1980-01-01" />);
expect(log).toEqual([
'node.setAttribute("data-reactroot", "")',
'node.setAttribute("type", "date")',
'node.setAttribute("value", "1980-01-01")',
'node.value = ""',
'node.value = ""',
'node.setAttribute("checked", "")',
'node.setAttribute("checked", "")',
]);
});
});

0 comments on commit 44fa2c8

Please sign in to comment.