Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot type decimal point if value bound to array element #2759

Closed
yhylord opened this issue May 14, 2019 · 5 comments
Closed

Cannot type decimal point if value bound to array element #2759

yhylord opened this issue May 14, 2019 · 5 comments
Labels

Comments

@yhylord
Copy link

yhylord commented May 14, 2019

For this snippet of code:

<script>
	let array = [0], variable = 0;
</script>
<label>
	You cannot type a decimal point in this:<br>
	<input type=number step=0.01 bind:value={array[0]}>
</label>
<label>
	...But you can if you bind it to a variable instead:<br>
	<input type=number step=0.01 bind:value={variable}>
</label>

I can only type a decimal point in the second input, not in the first. Somehow binding the value to an array elements breaks things.

Being able to bind values to an array is useful for calculating averages, sums, etc. If anyone knows a workaround for now, please comment as well!

@yhylord yhylord changed the title Cannot type decimal point in input[type=number] if bound to array element Cannot type decimal point if value bound to array element May 14, 2019
@mrkishi
Copy link
Member

mrkishi commented May 14, 2019

That's indeed a bug in Svelte currently.

For now, you can use on:input instead of bindings to keep track of the value.

@Conduitry Conduitry added the bug label Jun 25, 2019
@primos63
Copy link

primos63 commented Jul 3, 2019

I just finished creating a fix for this, but want to test it a bit more before submitting a PR. Also need to see if some of my changes are required on the SSR side.

Binding to an array or object is indeed broken. It only appears to work because a test for typeof a === 'object' is true for both an array and obviously an object. If that test was not there, the value would never be marked as dirty.

Code sample:

<script>
	let array = [0, 1];
	let variable = { "num": 0.03 };
	let number = 0;
</script>
<input type=number step=0.01  bind:value={array[1]}>
<input type=number step=0.02  bind:value={number}>
<input type=number step=0.03 bind:value={variable["num"]}>

The context, $$.ctx, is initialized with references to variables rather than values in instance:

function instance($$self, $$props, $$invalidate) {
        ...
	return {
		array,
		variable,
		number,
		input0_input_handler,
		input1_input_handler,
		input2_input_handler
	};
}

The comparison that takes place when entering a number

function input0_input_handler() {
	array[1] = to_number(this.value);
	$$invalidate('array', array);
}

$$$invalidate is the instance method where key = 'array' and value is array (reference value)

instance(component, props, (key, value) => {
	if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) {
		if ($$.bound[key]) $$.bound[key](value);
		if (ready) make_dirty(component, key);
	}
})

so $$.ctx[key] and value are always the same. You can see in the safe_not_equal function that given a and b are references to the same variable, the only reason the field is marked dirty is due to the variables being objects. It's also marked dirty on every input event. That's why 0.0 reverts to just 0 in the input field.

export function safe_not_equal(a, b) {
	return a != a ? b == b : a !== b || ((a && typeof a === 'object') || typeof a === 'function');
}

@dasZGFz
Copy link
Contributor

dasZGFz commented Nov 26, 2019

Seems like this was solved: REPL

@Conduitry
Copy link
Member

I think this was fixed in 3.10.0 along with #3426 by #3506, but I'm not sure how to write a test for this. JSDOM doesn't seem to be cooperating.

@Conduitry
Copy link
Member

It's probably not worth it to struggle with JSDOM on this, likely fruitlessly. Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants