bind:value as Date support for <input type=date> tags

* (breaking change) changes the current `bind:value` behavior that returns a date string of `yyyy-mm-dd` so that it will return a `Date` value instead.
pull/3494/head
Colin Casey 6 years ago
parent 5b4758f0f8
commit 355d43c00e

@ -325,6 +325,10 @@ function get_value_from_dom(
return `@to_number(this.${name})`;
}
if (type === 'date') {
return `@value_as_date(this.${name})`;
}
if ((name === 'buffered' || name === 'seekable' || name === 'played')) {
return `@time_ranges_to_array(this.${name})`;
}

@ -64,6 +64,11 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
node.attributes.some((attribute) => attribute.name === 'contenteditable')
);
const is_date_input = (
node.name === 'input' &&
node.attributes.some((attribute) => attribute.name === 'type' && attribute.get_static_value() === 'date')
);
const slot = node.get_static_attribute_value('slot');
const component = node.find_nearest(/InlineComponent/);
if (slot && component) {
@ -162,6 +167,9 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
} else if (binding.name === 'value' && node.name === 'textarea') {
const snippet = snip(expression);
node_contents = '${(' + snippet + ') || ""}';
} else if (binding.name === 'value' && is_date_input) {
const snippet = snip(expression);
opening_tag += '${@add_attribute("' + name + '", @date_as_value(' + snippet + '), 1)}';
} else {
const snippet = snip(expression);
opening_tag += '${@add_attribute("' + name + '", ' + snippet + ', 1)}';

@ -125,6 +125,22 @@ export function to_number(value) {
return value === '' ? undefined : +value;
}
export function value_as_date(value) {
const valueAsDate = new Date(value);
return isNaN(valueAsDate.getTime()) ? undefined : valueAsDate;
}
export function date_as_value(date) {
const validDate = Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime());
if (!validDate) {
return '';
}
const yyyy = date.getUTCFullYear();
const mm = date.getUTCMonth() + 1 < 10 ? `0${date.getUTCMonth() + 1}` : date.getUTCMonth() + 1;
const dd = date.getUTCDate() < 10 ? `0${date.getUTCDate()}` : date.getUTCDate();
return `${yyyy}-${mm}-${dd}`;
}
export function time_ranges_to_array(ranges) {
const array = [];
for (let i = 0; i < ranges.length; i += 1) {
@ -170,7 +186,9 @@ export function set_data(text, data) {
}
export function set_input_value(input, value) {
if (value != null || input.value) {
if (Object.prototype.toString.call(value) === '[object Date]') {
input.value = date_as_value(value);
} else if (value != null || input.value) {
input.value = value;
}
}

@ -0,0 +1,55 @@
const SEP_03_2019_INPUT_VALUE = '2019-09-03';
const SEP_03_2019_DATE_VALUE = new Date(SEP_03_2019_INPUT_VALUE);
const OCT_07_2019_INPUT_VALUE = '2019-10-07';
const OCT_07_2019_DATE_VALUE = new Date(OCT_07_2019_INPUT_VALUE);
export default {
props: {
date: SEP_03_2019_DATE_VALUE
},
html: `
<input type=date>
<p>[object Date] ${SEP_03_2019_DATE_VALUE}</p>
`,
ssrHtml: `
<input type=date value='${SEP_03_2019_INPUT_VALUE}'>
<p>[object Date] ${SEP_03_2019_DATE_VALUE}</p>
`,
async test({ assert, component, target, window }) {
const input = target.querySelector('input');
assert.equal(input.value, SEP_03_2019_INPUT_VALUE);
assert.equal(component.date.toString(), SEP_03_2019_DATE_VALUE.toString());
const event = new window.Event('input');
input.value = OCT_07_2019_INPUT_VALUE;
await input.dispatchEvent(event);
assert.equal(component.date.toString(), OCT_07_2019_DATE_VALUE.toString());
assert.htmlEqual(target.innerHTML, `
<input type='date'>
<p>[object Date] ${OCT_07_2019_DATE_VALUE}</p>
`);
component.date = SEP_03_2019_DATE_VALUE;
assert.equal(input.value, SEP_03_2019_INPUT_VALUE);
assert.htmlEqual(target.innerHTML, `
<input type='date'>
<p>[object Date] ${SEP_03_2019_DATE_VALUE}</p>
`);
// empty string should be treated as undefined
input.value = '';
await input.dispatchEvent(event);
assert.equal(component.date, undefined);
assert.htmlEqual(target.innerHTML, `
<input type='date'>
<p>[object Undefined] undefined</p>
`);
},
};

@ -0,0 +1,6 @@
<script>
export let date;
</script>
<input type='date' bind:value={date}>
<p>{Object.prototype.toString.call(date)} {date}</p>
Loading…
Cancel
Save