Repository: sveltejs/svelte (JavaScript)
Date: 2017-04-02 21:44:36+00:00
Task type: Bug Fix

Issue:
<input type='number' bind:value> — value should be a number
It makes no sense to treat `input.value` as a string if `input.type === 'number'`. The same goes for `range`.


Issue discussion:

Solution patch:
diff --git a/src/generators/dom/visitors/attributes/addElementBinding.js b/src/generators/dom/visitors/attributes/addElementBinding.js
--- a/src/generators/dom/visitors/attributes/addElementBinding.js
+++ b/src/generators/dom/visitors/attributes/addElementBinding.js
@@ -144,6 +144,11 @@ function getBindingValue ( generator, local, node, attribute, isMultipleSelect,
 		return `${local.name}.__value`;
 	}
 
+	// <input type='range|number' bind:value>
+	if ( type === 'range' || type === 'number' ) {
+		return `+${local.name}.${attribute.name}`;
+	}
+
 	// everything else
 	return `${local.name}.${attribute.name}`;
 }


Test patch:
diff --git a/test/generator/samples/binding-input-number/_config.js b/test/generator/samples/binding-input-number/_config.js
new file mode 100644
--- /dev/null
+++ b/test/generator/samples/binding-input-number/_config.js
@@ -0,0 +1,33 @@
+export default {
+	data: {
+		count: 42
+	},
+
+	html: `
+		<input type='number'>
+		<p>number 42</p>
+	`,
+
+	test ( assert, component, target, window ) {
+		const input = target.querySelector( 'input' );
+		assert.equal( input.value, '42' );
+
+		const event = new window.Event( 'input' );
+
+		input.value = '43';
+		input.dispatchEvent( event );
+
+		assert.equal( component.get( 'count' ), 43 );
+		assert.htmlEqual( target.innerHTML, `
+			<input type='number'>
+			<p>number 43</p>
+		` );
+
+		component.set({ count: 44 });
+		assert.equal( input.value, '44' );
+		assert.htmlEqual( target.innerHTML, `
+			<input type='number'>
+			<p>number 44</p>
+		` );
+	}
+};
diff --git a/test/generator/samples/binding-input-number/main.html b/test/generator/samples/binding-input-number/main.html
new file mode 100644
--- /dev/null
+++ b/test/generator/samples/binding-input-number/main.html
@@ -0,0 +1,2 @@
+<input type='number' bind:value='count'>
+<p>{{typeof count}} {{count}}</p>
diff --git a/test/generator/samples/binding-input-range/_config.js b/test/generator/samples/binding-input-range/_config.js
new file mode 100644
--- /dev/null
+++ b/test/generator/samples/binding-input-range/_config.js
@@ -0,0 +1,33 @@
+export default {
+	data: {
+		count: 42
+	},
+
+	html: `
+		<input type='range'>
+		<p>number 42</p>
+	`,
+
+	test ( assert, component, target, window ) {
+		const input = target.querySelector( 'input' );
+		assert.equal( input.value, '42' );
+
+		const event = new window.Event( 'input' );
+
+		input.value = '43';
+		input.dispatchEvent( event );
+
+		assert.equal( component.get( 'count' ), 43 );
+		assert.htmlEqual( target.innerHTML, `
+			<input type='range'>
+			<p>number 43</p>
+		` );
+
+		component.set({ count: 44 });
+		assert.equal( input.value, '44' );
+		assert.htmlEqual( target.innerHTML, `
+			<input type='range'>
+			<p>number 44</p>
+		` );
+	}
+};
diff --git a/test/generator/samples/binding-input-range/main.html b/test/generator/samples/binding-input-range/main.html
new file mode 100644
--- /dev/null
+++ b/test/generator/samples/binding-input-range/main.html
@@ -0,0 +1,2 @@
+<input type='range' bind:value='count'>
+<p>{{typeof count}} {{count}}</p>