Yesterday I was trying to translate a problem I had to solve in React, to Svelte, and I can't figure it out.
The problem is the following:
In react is fairly easy, declare a function that takes, the event and a variable to know which input I'm taking the event from. Do the proper validations and done.
Sadly in svelte I have almost 0 experience, and I don't know how to tackle it. This the code so far (spoiler alert it does not even get close to do what is supposed to do). Svelte REPL
Running a console.log to show the value of sp1, inside the function that validates it, and outside the function (before and after the function), shows what I do expect:
So the validation and assignment of the correct value takes place, nonetheless the input keep showing wrong value (ex: input shows 112 and the value should be 100).
A more dynamic way to do this would be using arrays.
let inputs = [{
value: 0,
color: 'GRAY'
}, {
value: 0,
color: 'DARKSLATEGRAY'
}, {
value: 0,
color: 'TEAL'
}];
This would also make calculations easier since we can use the array methods. It would also enable us to use each
blocks which remove redundant code. Then we will use a function called validate
and pass the index of the current input to it. Using the input
we can calculate the maximum possible value that can be entered in that input
and set the input
if it crosses that maximum value. This validate
function will be called from the template on the input
event.
Here's the code.
<script>
let total = 100;
let inputs = [{
value: 0,
color: 'GRAY'
}, {
value: 0,
color: 'DARKSLATEGRAY'
}, {
value: 0,
color: 'TEAL'
}];
$: spOthers = total - inputs.map(x => x.value || 0).reduce((a, b) => a + b);
function validate(index) {
let maxInput = total - inputs.map(x => x.value).filter((x, i) => i !== index).reduce((a, b) => a + b);
if (inputs[index].value > maxInput) {
inputs[index].value = maxInput;
}
}
</script>
{#each inputs as {value, color}, i}
<div class='input-container'>
<div class='square' style="background-color: {color}" />
<input type="number" min="0" class='input' bind:value={value} on:input={() => validate(i)} />
</div>
{/each}
<div class='input-container'>
<div class='square' style="background-color: DARKORANGE" />
<input type='number' class='input input-others' bind:value={spOthers} disabled/>
</div>
Note: I have omitted the styles above as there are no changes in them.
Here is a working REPL.