Quantcast
Channel: Active questions tagged svelte - Stack Overflow
Viewing all articles
Browse latest Browse all 1541

Idiomatic way in Svelte to do two way binding with an intermediate transformation

$
0
0

Two way binding is great and elegant in Svelte, but a recurrent situation I've come across is needing two way binding with an intermediate transformation that converts types or does some kind of clean up. For example:

  • Binding to a select component's prop value that has the form {value, label}, but its parent just handles a value
  • Type conversions, where a <input type=text> is also input for some other type (Number, date, custom one), or an input to edit an object as JSON that could also be changed from the outside.

My question is: Which is a good, idiomatic and simple way of solving this pattern in Svelte?

The best reusable solution I've found so far has been to create a store factory for one-to-one transformations that returns two stores, a and b which you can then use and bind to other components:

Example: play with REPL here

// App.svelte<script>    import oneToOne from './oneToOne.js'    const f = x => JSON.stringify({x});    const fInv = x => {try{return JSON.parse(x).x} catch(err){return NaN}};    let [a, b] = oneToOne(13, f, fInv); </script>A: <input bind:value={$a}/>B: <input bind:value={$b}/>
// oneToOne.jsimport { writable } from 'svelte/store';const identity = x => x;export default function oneToOne(val, f = identity, fInv = identity) {    let fInvB = val;    let fA = f(val);    const A = writable(fInvB);    const B = writable(fA);    B.subscribe((b) => {            if(fA !== b && !(Number.isNaN(fA) && Number.isNaN(b))) {                        fInvB = fInv(b);            fA = b;                     A.set(fInvB)        }    });     A.subscribe((a) => {                if(fInvB !== a && !(Number.isNaN(fInvB) && Number.isNaN(a))) {                       fA = f(a);              fInvB = a;                      B.set(fA)        }    });     return [A, B];}

Does this make sense? Am I missing a simpler way of doing this or avoiding this complexity altogether?


Viewing all articles
Browse latest Browse all 1541

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>