1

I am completely new to Svelte (or other JavaScript reactive framework). I worked for years only with jQuery. Let us assume, ich have the following arrays and a formatter function ...

let quotes = [{
  "key": "moonpie",
  "price": 2.22222222,
  "dif": 1.009
} ....]

let securities = [{
  "key": "moonpie",
  "stock": 200
} .....]

function updateQuotesWithinInterval {
  ... do some stuff, get the data ...
  quotes = json;
}

function formatNumber(value, options) {
  // 2.2222222 comes in, 2.22 EUR goes out
  // 1.000007 comes in, +1.00% goes out ....
  return formatted value;
}

{#each securities as security}
  Name: {security.key}<br />
  Price: {formatNumber(quotes[security.name].price, someoptionhere)}<br /> --> 2.22 EUR formatted
  Credit: {formatNumber(securities.stock * quotes[securities.name].price, someoptionshere}<br /> --> 2000 * 2.222222222 = 4,444.44 EUR formatted
  Change: {formatNumber(quotes[security.name].change, someoptionhere)}<br /> --> +1.01% formatted
{/each}

So, what is the common approach, to display the data formatted by calling the JavaScript function after updates via XHR in a foreach statement?

Initially it works and with a button click event, it does as well, but does not work when the array changes without interaction from an interval fetch.

I was thinking then, that I need a new array with the formatted values and displaying them - this works, but I was wondering, whether this is the common approach?

I need the data unformatted, so that I can perform some calculations on the client side, so I can not pick them up formatted.

So, when I am assigning new array, lets call them arrays with formatted values, then everything works find, but I am just not yet sure, whether this is the common approach for this problem, when updating data via XHR from polling or web sockets

2
  • quotes[security.name] should resolve as undefined because quotes is an array. I would first consider merging these two things into a single array via the derived store or on a backend and then iterate over the resulting structure. Commented Jan 26, 2023 at 8:33
  • Yes, you're absolutelly right, that was an example an not the question here ;) ... I was just writing it down as an example
    – Doe
    Commented Jan 26, 2023 at 8:36

1 Answer 1

2

So assuming you have 2 arrays both of which can update independently, and you need to display merged results.

Create 3 svelte stores, 2 for your original arrays and 1 for the derived merged array.

Each time you change one of the original stores, the derived will be recalculated, assuming it has subscribers.

stores.js

import { derived, writable } from "svelte/store";

/** @type {SvelteStore<{key: string, price: number, dif: number}[]>} */
export const quotes = writable([]);

/** @type {SvelteStore<{key: string, stock: number}[]>} */
export const securities = writable([]);

/** @type {SvelteStore<{key: string, stock: number, price:number, dif:number }[]>} */
export const securities_with_quotes = derived([quotes, securities], ([$quotes, $securities]) => {
    return $securities.map((security) => {
        let quote = $quotes.find(q => q.key == security.key);
        return {
            ...security,
            ...quote
        }
    });
})

Iterate over your resulting array inside your component. Because you are iterating over the derived store, all the changes in original arrays will trigger rerenders.

SecuritiesList.svelte

<script>
import {securities, quotes, securities_with_quotes } from "./stores.js";
import Price from 'Price.svelte'

function updateQuotesWithinInterval {
  ... do some stuff, get the data ...
  $quotes = json;
} 

</script>

{#each $securities_with_quotes as security}
    Name: {security.key}
    Price: <Price value={security.price}/>
    Credit: <Price value={security.price * security.stock}/>
    Change: <Price value={security.dif}/>
{/each}

Isolating price with all it's display logic in a separate component is also a good idea.

Price.svelte

<script>
export let value = 0;

function formatNumber(value, options) {
  // 2.2222222 comes in, 2.22 EUR goes out
  // 1.000007 comes in, +1.00% goes out ...
  return formatted_value;
}

$:displayValue = formatNumber(value)
</script>

{displayValue}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.