Svelte – Creating a CRUD application

In this article we will learn how to do operations like create, read, update and delete by developing a CRUD application in Svelte. These are the most basic operations which completes the flow from constructor to destructor.

Let’s understand each of these operations one by one. But before that we should have a brief idea of what we are going to create.

In this post, we will design a superhero app in which you can add, delete and update members of Avengers, Justice League and X-men. Let’s get started.

Read Operation

To read or display the data in application, we need to first have some data. So, let’s create an array of few default superhero entries. We will consider few attributes like name, weapon and team. Also, we will create a form for adding a new entry.

<script>
  const superhero = [
    {
      name: 'Captain America',
      weapon: 'Shield',
      team: 'Avengers',
    },
    {
      name: 'Flash',
      weapon: 'Speed',
      team: 'Justice League',
    },
    {
      name: 'Wolverine',
      weapon: 'Claws',
      team: 'X-Men',
    },
  ]
</script>

This superhero array will be used to store entries. We are hard coding 3 entries so that when the app loads, there exists some data in the table. Let’s show this in an html table –

<script>
  const superhero = [
    {
      name: 'Captain America',
      weapon: 'Shield',
      team: 'Avengers',
    },
    {
      name: 'Flash',
      weapon: 'Speed',
      team: 'Justice League',
    },
    {
      name: 'Wolverine',
      weapon: 'Claws',
      team: 'X-Men',
    },
  ]
</script>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Weapon</th>
      <th>Team</th>
    </tr>
  </thead>
  <tbody>
    {#each superhero as singlehero, index (index)}
    <tr>
      <td>{singlehero.name}</td>
      <td>{singlehero.weapon}</td>
      <td>{singlehero.team}</td>
    </tr>
    {/each}
  </tbody>
</table>

The rendered table will look like this –

Superhero table - Read operation for CRUD on Svelte

Create Operation

In our example, the create operation involves creating a new superhero entry. For that we need a form with fields – Name, Weapon and Team. Let’s create it –

<div>
  <form>
    <label for='name'>Name</label>
    <input 
      type="text" 
      placeholder="Name of superhero" 
      name="name"
      required 
      
    />
    <br />
    <label for='weapon'>Weapon</label>
    <input 
      type="text" 
      placeholder="Weapon" 
      name="weapon" 
      required
       
    />
    <br />
    <label for='team'>Team</label>
    <select 
      name="team" 
      required
      
    >
      <option value={'Avengers'}>Avengers</option>
      <option value={'Justice League'}>Justice League</option>
      <option value={'X-Men'}>X-Men</option>
    </select>
    <br /><br />
    <input type="submit" />
  </form>
</div>

It’s a simple html code with 2 input fields and 1 select field. Let’s create reactive variables to bind the values of these fields.

<script>
  let superheroName = "";
  let superheroWeapon = "";
  let superheroTeam = "";

  // superhero object and other code
</script>

We have created 3 variables – superheroName, superheroWeapon and superheroTeam. Now we will bind them to the form fields –

<script>
  let superheroName = "";
  let superheroWeapon = "";
  let superheroTeam = "";

  // other code
</script>

<div>
  <form>
    <label for='name'>Name</label>
    <input 
      type="text" 
      placeholder="Name of superhero" 
      name="name"
      required 
      bind:value={superheroName} 
    />
    <br />
    <label for='weapon'>Weapon</label>
    <input 
      type="text" 
      placeholder="Weapon" 
      name="weapon" 
      required
      bind:value={superheroWeapon} 
    />
    <br />
    <label for='team'>Team</label>
    <select 
      name="team" 
      required
      bind:value={superheroTeam} 
    >
      <option value={'Avengers'}>Avengers</option>
      <option value={'Justice League'}>Justice League</option>
      <option value={'X-Men'}>X-Men</option>
    </select>
    <br /><br />
    <input type="submit" />
  </form>
</div>

With the help of this binding, we can get the values of input and select fields in the variables. The step is to create a function which will get called on submitting the form. This function will append the newly created superhero into our superhero array.

function submitForm(e) {
  // Prevent page reload on
  // pressing submit button
  e.preventDefault();

  // Push the new superhero object
  // into array
  superhero.push({
      name: superheroName,
      weapon: superheroWeapon,
      team: superheroTeam
  });

  // Reassign the array for
  // reactivity
  superhero = superhero;

  // Empty the form after submit
  superheroName = "";
  superheroTeam = "";
  superheroWeapon = "";
}

Keep in mind that you need to reassign the array after pushing the new object. Learn more, why reassignment is necessary.

This concludes the create operation. The complete code till this stage looks like this –

<script>
  let superheroName = "";
  let superheroWeapon = "";
  let superheroTeam = "";

  const superhero = [
    {
      name: "Captain America",
      weapon: "Shield",
      team: "Avengers"
    },
    {
      name: "Flash",
      weapon: "Speed",
      team: "Justice League"
    },
    {
      name: "Wolverine",
      weapon: "Claws",
      team: "X-Men"
    }
  ];

  function submitForm(e) {
    e.preventDefault();

    superhero.push({
      name: superheroName,
      weapon: superheroWeapon,
      team: superheroTeam
    });

    superhero = superhero;
    superheroName = "";
    superheroTeam = "";
    superheroWeapon = "";
  }
</script>

<div>
  <form on:submit={submitForm}>
    <label for='name'>Name</label>
    <input 
      type="text" 
      placeholder="Name of superhero" 
      name="name"
      required 
      bind:value={superheroName} 
    />
    <br />
    <label for='weapon'>Weapon</label>
    <input 
      type="text" 
      placeholder="Weapon" 
      name="weapon" 
      required
      bind:value={superheroWeapon} 
    />
    <br />
    <label for='team'>Team</label>
    <select 
      name="team" 
      required
      bind:value={superheroTeam} 
    >
      <option value={'Avengers'}>Avengers</option>
      <option value={'Justice League'}>Justice League</option>
      <option value={'X-Men'}>X-Men</option>
    </select>
    <br /><br />
    <input type="submit" />
  </form>
</div>
<hr />
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Weapon</th>
      <th>Team</th>
    </tr>
  </thead>
  <tbody>
    {#each superhero as singlehero, index (index)}
    <tr>
      <td>{singlehero.name}</td>
      <td>{singlehero.weapon}</td>
      <td>{singlehero.team}</td>
    </tr>
    {/each}
  </tbody>
</table>
Create operation in CRUD Svelte with html form to add a new superhero into the table

Update Operation

Updating a value means changing the already existing entry. For that we need 2 things –

  1. A link or button to let the code know that we want to update particular entry.
  2. Making form compatible to handle update operation.

Let’s first create edit link. For this, we will add one more column in our table.

// Script, form and table header here
...
  <tbody>
    {#each superhero as singlehero, index (index)}
    <tr>
      <td>{singlehero.name}</td>
      <td>{singlehero.weapon}</td>
      <td>{singlehero.team}</td>
      <td>
        <a 
          href="#" 
          on:click={() => editSuperhero(index)}>
          Edit
        </a>
      </td>
    </tr>
    {/each}
  </tbody>
...

We created an anchor link which will call editSuperhero function on click. We are passing the index of the element so that we can know which element link is clicked and needs to be updated. Let’s create editSuperhero function –

let editEntryIndex = -1;

function editSuperhero(index) {
  editEntryIndex = index;
  superheroName = superhero[editEntryIndex].name;
  superheroTeam = superhero[editEntryIndex].team;
  superheroWeapon = superhero[editEntryIndex].weapon;
}

Here we declared one more reactive variable editEntryIndex. The role of this variable is to indicate if there is a request to update an entry and which one to update. If it’s value is -1 then we are considering that no entry needs to be updated otherwise it will hold the index.

Function editSuperhero is simply setting the reactive variables to the value of object in superhero array at selected index. By doing this, our form will auto fill with these values.

It will look like this –

Update CRUD operation in Svelte. Form filled with values of selected entry when edit button is clicked

Now when we submit the form, a new entry will be created. But we want to update the selected entry. So, we need to make few changes in submitForm function. Basically we need to tell the function that it’s an update operation and we don’t want to append a new entry else update an existing entry. Check the code –

function submitForm(e) {
  e.preventDefault();

  if (editEntryIndex > -1) {
    superhero[editEntryIndex] = {
      name: superheroName,
      weapon: superheroWeapon,
      team: superheroTeam
    };
  } else {
    superhero.push({
      name: superheroName,
      weapon: superheroWeapon,
      team: superheroTeam
    });
  }

  superhero = superhero;
  superheroName = "";
  superheroTeam = "";
  superheroWeapon = "";
  editEntryIndex = -1;
}

In submitForm function we added a condition to check if editEntryIndex value is greater than -1. If it is then the entry in superhero array at editEntryIndex index will be changed. Otherwise a new entry is pushed. Also, we are setting editEntryIndex to -1 to close the update operation.

The complete code up to this stage looks like this –

<script>
  let superheroName = "";
  let superheroWeapon = "";
  let superheroTeam = "";
  let editEntryIndex = -1;

  const superhero = [
    {
      name: "Captain America",
      weapon: "Shield",
      team: "Avengers"
    },
    {
      name: "Flash",
      weapon: "Speed",
      team: "Justice League"
    },
    {
      name: "Wolverine",
      weapon: "Claws",
      team: "X-Men"
    }
  ];

  function submitForm(e) {
    e.preventDefault();

    if (editEntryIndex > -1) {
      superhero[editEntryIndex] = {
        name: superheroName,
        weapon: superheroWeapon,
        team: superheroTeam
      };
    } else {
      superhero.push({
        name: superheroName,
        weapon: superheroWeapon,
        team: superheroTeam
      });
    }

    superhero = superhero;
    superheroName = "";
    superheroTeam = "";
    superheroWeapon = "";
    editEntryIndex = -1;
  }

  function editSuperhero(index) {
    editEntryIndex = index;
    superheroName = superhero[editEntryIndex].name;
    superheroTeam = superhero[editEntryIndex].team;
    superheroWeapon = superhero[editEntryIndex].weapon;
  }
</script>

<div>
  <form on:submit={submitForm}>
    <label for='name'>Name</label>
    <input 
      type="text" 
      placeholder="Name of superhero" 
      name="name"
      required 
      bind:value={superheroName} 
    />
    <br />
    <label for='weapon'>Weapon</label>
    <input 
      type="text" 
      placeholder="Weapon" 
      name="weapon" 
      required
      bind:value={superheroWeapon} 
    />
    <br />
    <label for='team'>Team</label>
    <select 
      name="team" 
      required
      bind:value={superheroTeam} 
    >
      <option value={'Avengers'}>Avengers</option>
      <option value={'Justice League'}>Justice League</option>
      <option value={'X-Men'}>X-Men</option>
    </select>
    <br /><br />
    <input type="submit" />
  </form>
</div>
<hr />
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Weapon</th>
      <th>Team</th>
    </tr>
  </thead>
  <tbody>
    {#each superhero as singlehero, index (index)}
    <tr>
      <td>{singlehero.name}</td>
      <td>{singlehero.weapon}</td>
      <td>{singlehero.team}</td>
      <td>
        <a 
          href="#" 
          on:click={() => editSuperhero(index)}>
          Edit
        </a>
      </td>
    </tr>
    {/each}
  </tbody>
</table>

Delete Operation

In order to delete an entry, we just need to know it’s position in array. Then we can use array splice method to remove it. So, we will create one more column in our table to add delete link, just like we did for edit link and pass the index to delete function.

// Script, form and table header here
...
  <tbody>
    {#each superhero as singlehero, index (index)}
    <tr>
      <td>{singlehero.name}</td>
      <td>{singlehero.weapon}</td>
      <td>{singlehero.team}</td>
      <td>
        <a 
          href="#" 
          on:click={() => editSuperhero(index)}>
          Edit
        </a>
      </td>
      <td>
        <a 
          href="#" 
          on:click={() => deleteSuperhero(index)}>
          Delete
        </a>
      </td>
    </tr>
    {/each}
  </tbody>
...

Code for deleteSuperhero function –

function deleteSuperhero(index){
  superhero.splice(index, 1)
  superhero = superhero
}

Here concludes all the operations of CRUD.

Complete CRUD code

<script>
  let superheroName = "";
  let superheroWeapon = "";
  let superheroTeam = "";
  let editEntryIndex = -1;

  const superhero = [
    {
      name: "Captain America",
      weapon: "Shield",
      team: "Avengers"
    },
    {
      name: "Flash",
      weapon: "Speed",
      team: "Justice League"
    },
    {
      name: "Wolverine",
      weapon: "Claws",
      team: "X-Men"
    }
  ];

  function submitForm(e) {
    e.preventDefault();

    if (editEntryIndex > -1) {
      superhero[editEntryIndex] = {
        name: superheroName,
        weapon: superheroWeapon,
        team: superheroTeam
      };
    } else {
      superhero.push({
        name: superheroName,
        weapon: superheroWeapon,
        team: superheroTeam
      });
    }

    superhero = superhero;
    superheroName = "";
    superheroTeam = "";
    superheroWeapon = "";
    editEntryIndex = -1;
  }

  function editSuperhero(index) {
    editEntryIndex = index;
    superheroName = superhero[editEntryIndex].name;
    superheroTeam = superhero[editEntryIndex].team;
    superheroWeapon = superhero[editEntryIndex].weapon;
  }

  function deleteSuperhero(index){
    superhero.splice(index, 1)
    superhero = superhero
  }
</script>

<div>
  <form on:submit={submitForm}>
    <label for='name'>Name</label>
    <input 
      type="text" 
      placeholder="Name of superhero" 
      name="name"
      required 
      bind:value={superheroName} 
    />
    <br />
    <label for='weapon'>Weapon</label>
    <input 
      type="text" 
      placeholder="Weapon" 
      name="weapon" 
      required
      bind:value={superheroWeapon} 
    />
    <br />
    <label for='team'>Team</label>
    <select 
      name="team" 
      required
      bind:value={superheroTeam} 
    >
      <option value={'Avengers'}>Avengers</option>
      <option value={'Justice League'}>Justice League</option>
      <option value={'X-Men'}>X-Men</option>
    </select>
    <br /><br />
    <input type="submit" />
  </form>
</div>
<hr />
<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Weapon</th>
      <th>Team</th>
    </tr>
  </thead>
  <tbody>
    {#each superhero as singlehero, index (index)}
    <tr>
      <td>{singlehero.name}</td>
      <td>{singlehero.weapon}</td>
      <td>{singlehero.team}</td>
      <td>
        <a 
          href="#" 
          on:click={() => editSuperhero(index)}>
          Edit
        </a>
      </td>
      <td>
        <a 
          href="#" 
          on:click={() => deleteSuperhero(index)}>
          Delete
        </a>
      </td>
    </tr>
    {/each}
  </tbody>
</table>

    Tweet this to help others

Live Demo

Open Live Demo