Skip to content

Commit

Permalink
code improvement/refactoring!! svelte's "bind" updates parent variabl…
Browse files Browse the repository at this point in the history
…e multiple times

when variable data is an array (and objects too according to sveltejs/svelte#4265 (comment))

😲😲😲😭😭😭😭

the issue seems to be an issue with svelte for all svelte devs (not just me 😇).
Here is the issue page: sveltejs/svelte#4265
And here is a REPL for an idea of the issue: https://svelte.dev/repl/316c01d1b3b34a259b8fdba66f6ee14e?version=4.0.1

*The alternative* 😉🙌😄
replacing with update functions the update variable in parent component (similar to component binding) and event handlers (similar to element/input binding)

*other bits & bobs*😁😁
type safety to KeyRepArea.svelte component
  • Loading branch information
arnard76 committed Jul 7, 2023
1 parent 34a474d commit 4a595e8
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 44 deletions.
14 changes: 11 additions & 3 deletions src/lib/exercises/EditingExercisePanel.svelte
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
<script lang="ts">
import { updateExercise } from "$lib/exercises/CRUD/crudDB";
import { updateExercise as updateExerciseOnDb } from "$lib/exercises/CRUD/crudDB";
import type Exercise from "$lib/exercises";
import FocusLimbsList from "./FocusLimbsList.svelte";
export let exercise: Exercise;
export let exerciseId: string;
export let updateExercise: (updatedExercise: Exercise) => void;
</script>

<div
style="width: 100%; height: 100%; display:flex; flex-direction:column; align-items:flex-start;"
>
<button type="button" on:click={() => updateExercise(exerciseId, exercise)}>
<button
type="button"
on:click={() => updateExerciseOnDb(exerciseId, exercise)}
>
Update Database
</button>

<FocusLimbsList bind:focusLimbs={exercise.focusLimbs} />
<FocusLimbsList
focusLimbs={exercise.focusLimbs}
updateFocusLimbs={(updated) =>
updateExercise({ ...exercise, focusLimbs: updated })}
/>
</div>
27 changes: 23 additions & 4 deletions src/lib/exercises/FocusLimb.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
export let focusLimbName: string;
export let keyRepAreas: KeyRepArea[];
export let startKeyRepAreaIsEnd: boolean;
export let updateStartKeyRepAreaIsEnd: (updated: boolean) => void;
export let updateKeyRepAreas: (updated: KeyRepArea[]) => void;
function makeEndKRASameAsStart() {
keyRepAreas[keyRepAreas.length - 1] = keyRepAreas[0];
Expand All @@ -17,22 +19,39 @@
);
}
$: startKeyRepAreaIsEnd ? makeEndKRASameAsStart() : seperateStartEnd();
function addKRA() {
exercises.addKRAToSelectedExercise(focusLimbName, new KeyRepArea());
}
function onCheckboxChange({ target }: Event) {
// because typescript doesn't work in the HTML section 🤔
onStartEndSameChange((target as HTMLInputElement).checked);
}
function onStartEndSameChange(updated: boolean) {
updated ? makeEndKRASameAsStart() : seperateStartEnd();
updateStartKeyRepAreaIsEnd(updated);
updateKeyRepAreas(keyRepAreas);
}
onStartEndSameChange(startKeyRepAreaIsEnd);
</script>

<div class="KRAs-for-limb">
<h3>{focusLimbName}</h3>

<div>
start & end point (key rep area) are same?
<input type="checkbox" name="" id="" bind:checked={startKeyRepAreaIsEnd} />
<input
type="checkbox"
name=""
id=""
on:change={onCheckboxChange}
checked={startKeyRepAreaIsEnd}
/>
</div>

<KRAsList bind:keyRepAreas {focusLimbName} />
<KRAsList {keyRepAreas} {updateKeyRepAreas} {focusLimbName} />
<button type="button" on:click={() => addKRA()}> Add new KRA </button>
</div>

Expand Down
16 changes: 12 additions & 4 deletions src/lib/exercises/FocusLimbsList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import FocusLimb from "./FocusLimb.svelte";
export let focusLimbs: Exercise["focusLimbs"];
export let updateFocusLimbs: (updated: Exercise["focusLimbs"]) => void;
function addKRA(focusLimbName: string) {
exercises.addKRAToSelectedExercise(focusLimbName, new KeyRepArea());
Expand All @@ -35,12 +36,19 @@
</div>

<div style="width: 100%;overflow-y:scroll;">
{#each Object.entries(focusLimbs) as [focusLimbName, _] (focusLimbName)}
{#each Object.entries(focusLimbs) as [focusLimbName, { keyRepAreas, startKeyRepAreaIsEnd }] (focusLimbName)}
<FocusLimb
{focusLimbName}
bind:keyRepAreas={focusLimbs[focusLimbName].keyRepAreas}
bind:startKeyRepAreaIsEnd={focusLimbs[focusLimbName]
.startKeyRepAreaIsEnd}
{keyRepAreas}
updateKeyRepAreas={(updated) => {
focusLimbs[focusLimbName].keyRepAreas = updated;
updateFocusLimbs(focusLimbs);
}}
{startKeyRepAreaIsEnd}
updateStartKeyRepAreaIsEnd={(updated) => {
focusLimbs[focusLimbName].startKeyRepAreaIsEnd = updated;
updateFocusLimbs(focusLimbs);
}}
/>
{/each}
</div>
Expand Down
13 changes: 11 additions & 2 deletions src/lib/exercises/KRAsList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@
export let focusLimbName: string;
export let keyRepAreas: KeyRepArea[];
export let updateKeyRepAreas: (updated: KeyRepArea[]) => void;
const onRelativeKeypointChange = ({ target }: Event, index: number) => {
keyRepAreas[index].relativeToWhichKeypoint = (
target as HTMLSelectElement
).selectedOptions[0].value;
updateKeyRepAreas(keyRepAreas);
};
</script>

{#each keyRepAreas as keyRepArea, index (index)}
{@const { areaSize, topLeft } = keyRepArea}
{@const { areaSize, topLeft, relativeToWhichKeypoint } = keyRepArea}
<div
class="key-rep-area"
style={`${
Expand All @@ -31,7 +39,8 @@

<SelectOneKeypointName
{keypointNames}
bind:selectedKeypoint={keyRepAreas[index].relativeToWhichKeypoint}
selectedKeypoint={relativeToWhichKeypoint}
on:change={(e) => onRelativeKeypointChange(e, index)}
/>

<button type="button" on:click={() => deleteKRA(focusLimbName, keyRepArea)}
Expand Down
20 changes: 11 additions & 9 deletions src/lib/key-rep-area/KeyRepArea.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
<script>
<script lang="ts">
import Keypoint from "$lib/pose-detection/Keypoint.svelte";
import Line from "$lib/pose-detection/StraightLine.svelte";
import selectedKeyRepArea from "$lib/key-rep-area/selected";
import type KeyRepArea from "./keyRepArea";
export let keyRepArea;
export let keypoints;
export let keyRepArea: KeyRepArea;
export let keypoints: any[];
export let focusKeypoint = null;
export let updateKeyRepAreas: (newKeyRepArea: KeyRepArea) => void;
let corners, inArea;
let corners, inArea: boolean;
const origin = { x: 0, y: 0 };
$: if (keyRepArea && keypoints) {
Expand All @@ -19,14 +21,16 @@
$: colour = inArea ? "green" : "lightgrey";
function moveTopLeft(e) {
function moveTopLeft(e: MouseEvent) {
keyRepArea.topLeft.x = keyRepArea.topLeft.x + e.offsetX;
keyRepArea.topLeft.y = keyRepArea.topLeft.y + e.offsetY;
updateKeyRepAreas(keyRepArea);
}
function adjustSize(e) {
function adjustSize(e: MouseEvent) {
keyRepArea.areaSize.width = keyRepArea.areaSize.width - e.offsetX;
keyRepArea.areaSize.height = keyRepArea.areaSize.height - e.offsetY;
updateKeyRepAreas(keyRepArea);
}
$: thisIsASelectedKRA = $selectedKeyRepArea == keyRepArea;
Expand All @@ -41,9 +45,7 @@
--KRA-bg-colour: {thisIsASelectedKRA
? 'rgba(25, 60, 150, 0.3)'
: 'rgba(0, 0, 0, 0.3)'};"
on:drag={(e) => {
moveTopLeft(e);
}}
on:drag={(e) => moveTopLeft(e)}
on:dragend={(e) => moveTopLeft(e)}
on:dblclick={(e) => selectedKeyRepArea.select(keyRepArea)}
>
Expand Down
7 changes: 6 additions & 1 deletion src/lib/key-rep-area/KeyRepAreas.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
export let keypoints: any[];
export let focusKeypointName: string;
export let startKeyRepAreaIsEnd: boolean | undefined = undefined;
export let updateKeyRepAreas: (updated: KeyRepArea[]) => void;
$: showingKeyRepAreas = startKeyRepAreaIsEnd
? [...keyRepAreas].slice(0, -1)
Expand All @@ -14,7 +15,11 @@

{#each showingKeyRepAreas as keyRepArea, index (keyRepArea)}
<KeyRepAreaComponent
bind:keyRepArea={keyRepAreas[index]}
{keyRepArea}
updateKeyRepAreas={(updated) => {
keyRepAreas[index] = updated;
updateKeyRepAreas(keyRepAreas);
}}
{keypoints}
focusKeypoint={focusKeypointName}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/lib/pose-detection/SelectOneKeypoint.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</script>

{#if keypointNames}
<select bind:value={selectedKeypoint}>
<select bind:value={selectedKeypoint} on:change>
{#each keypointNames as keypointName (keypointName)}
<option value={keypointName}
>{getVerboseKeypointName(keypointName)}</option
Expand Down
12 changes: 7 additions & 5 deletions src/routes/editing-key-rep-areas/edit-visually/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@
<!-- the divider so mouse events can interact with 👇 but not ☝️ -->
<div class="divider" />

{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { startKeyRepAreaIsEnd }] (focusLimb)}
{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { keyRepAreas, startKeyRepAreaIsEnd }] (focusLimb)}
<KeyRepAreas
bind:keyRepAreas={$exercises[$selectedExerciseId].focusLimbs[
focusLimb
].keyRepAreas}
{keyRepAreas}
updateKeyRepAreas={(updated) =>
($exercises[$selectedExerciseId].focusLimbs[focusLimb].keyRepAreas =
updated)}
{startKeyRepAreaIsEnd}
keypoints={$controlledKeypoints}
focusKeypointName={focusLimb}
Expand All @@ -54,7 +55,8 @@
</div>

<EditingExercisePanel
bind:exercise={$exercises[$selectedExerciseId]}
exercise={$selectedExercise}
updateExercise={(updated) => ($exercises[$selectedExerciseId] = updated)}
exerciseId={$selectedExerciseId}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@
<!-- the divider so mouse events can interact with 👇 but not ☝️ -->
<div class="divider" />

{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { startKeyRepAreaIsEnd }] (focusLimb)}
{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { keyRepAreas, startKeyRepAreaIsEnd }] (focusLimb)}
<KeyRepAreas
bind:keyRepAreas={$exercises[$selectedExerciseId].focusLimbs[
focusLimb
].keyRepAreas}
{keyRepAreas}
updateKeyRepAreas={(updated) =>
($exercises[$selectedExerciseId].focusLimbs[focusLimb].keyRepAreas =
updated)}
{startKeyRepAreaIsEnd}
keypoints={$controlledKeypoints}
focusKeypointName={focusLimb}
Expand All @@ -96,7 +97,8 @@
</div>

<EditingExercisePanel
bind:exercise={$exercises[$selectedExerciseId]}
exercise={$selectedExercise}
updateExercise={(updated) => ($exercises[$selectedExerciseId] = updated)}
exerciseId={$selectedExerciseId}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@
<!-- the divider so mouse events can interact with 👇 but not ☝️ -->
<div class="divider" />

{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { startKeyRepAreaIsEnd }] (focusLimb)}
{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { keyRepAreas, startKeyRepAreaIsEnd }] (focusLimb)}
<KeyRepAreas
bind:keyRepAreas={$exercises[$selectedExerciseId].focusLimbs[
focusLimb
].keyRepAreas}
{keyRepAreas}
updateKeyRepAreas={(updated) =>
($exercises[$selectedExerciseId].focusLimbs[focusLimb].keyRepAreas =
updated)}
{startKeyRepAreaIsEnd}
keypoints={$controlledKeypoints}
focusKeypointName={focusLimb}
Expand All @@ -78,7 +79,8 @@
</div>

<EditingExercisePanel
bind:exercise={$exercises[$selectedExerciseId]}
exercise={$selectedExercise}
updateExercise={(updated) => ($exercises[$selectedExerciseId] = updated)}
exerciseId={$selectedExerciseId}
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@
<!-- the divider so mouse events can interact with 👇 but not ☝️ -->
<div class="divider" />
{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { startKeyRepAreaIsEnd }] (focusLimb)}
{#each Object.entries($selectedExercise.focusLimbs) as [focusLimb, { keyRepAreas, startKeyRepAreaIsEnd }] (focusLimb)}
<KeyRepAreas
bind:keyRepAreas={$exercises[$selectedExerciseId].focusLimbs[
focusLimb
].keyRepAreas}
{keyRepAreas}
updateKeyRepAreas={(updated) =>
($exercises[$selectedExerciseId].focusLimbs[
focusLimb
].keyRepAreas = updated)}
{startKeyRepAreaIsEnd}
keypoints={$controlledKeypoints}
focusKeypointName={focusLimb}
Expand All @@ -125,7 +127,9 @@
</div>
<EditingExercisePanel
bind:exercise={$exercises[$selectedExerciseId]}
exercise={$selectedExercise}
updateExercise={(updated) =>
($exercises[$selectedExerciseId] = updated)}
exerciseId={$selectedExerciseId}
/>
</div>
Expand Down

0 comments on commit 4a595e8

Please sign in to comment.