Initialize modal with object, make changes to intermediary object, save/revert to parent component

Viewed 42

I'm trying to get a modal to be initialized with an object('s properties). Then be able to make changes within the modal, and then either cancel (don't save changes) or save (setting the temporary values to the bound object, thus giving the parent its data)

I have found this question on stackoverflow: binded object with temp editing in svelte

Which voices some of the same issues I've had. Though the accepted answer is flawed and doesn't consider nested properties, besides any update in the parent sets its value to be that of the child (even when the child value has not been set to be saved).

I've reproduced the issue in this small demo on repl: https://svelte.dev/repl/7ee93070005a4dd38d9fd3261816f3f1?version=3.23.2

My actual code looks a bit like this:

<Modal isOpen={isSavingModalShown} onRequestClose={() => isSavingModalShown = false}>
  <SaveVenueForm bind:venue onSaved={() => isSavingModalShown = false} />
</Modal>
<!-- SaveVenueForm.svelte -->
<script lang="ts">
  export let onSaved: () => void
  export let venue = {}
  
  let tempVenue: Venue
  
  const populate = () => {
    tempVenue = { ...venue } as Venue
  }
  
  $: venue, populate()
  
  const handleSubmit = async () => {
    venue = tempVenue
    onSaved()
  }
</script>

<input type="text" bind:value={tempVenue.name} />
<input type="text" bind:value={tempVenue.location.city} />
<button variant="contained" size="lg" on:click={handleSubmit}>Save venue</button>
1 Answers

Just get one of the many deep cloning libraries and use that instead of a simple spread when setting the temporary value. In modern browsers you can also use the native structuredClone function.

Currently, as soon as you change the city, the source object (the location) is modified, even if that is not shown in the UI right away. (REPL that forces the UI update)

Related