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 –
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>
Update Operation
Updating a value means changing the already existing entry. For that we need 2 things –
- A link or button to let the code know that we want to update particular entry.
- 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 –
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>