Introduction
This post is an attempt to create a simple CRUD operation using svelte js.
In order to learn some aspects of svelte, I thought of creating this simple use case.
Use case
- Perform create, update, delete and read.
- A simple note with title and content field.
Let us begin.
npx degit sveltejs/template svelte-crud-example
cd svelte-crud-example
npm install
npm run dev
Above mentioned are the basic steps to create a svelte project and run it on your browser http://localhost:5000/
I will use bootstrap 4 cdn link to style my page. So, goto your root folder locate index.html present in your public directory and add this:
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
/>
Now create a new file named Notes.svelte under src folder and add the below template:
<section>
<div class="container">
<div class="row mt-5">
<div class="col-md-6">
<div class="card p-2 shadow">
<div class="card-body">
<h5 class="card-title mb-4">Add New Note</h5>
<form>
<div class="form-group">
<label for="title">Title</label>
<input
type="text"
class="form-control"
id="text"
placeholder="Note Title" />
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea
class="form-control"
id="content"
rows="3"
placeholder="Note Content" />
</div>
<button type="submit" on:click|preventDefault={addNote} class="btn btn-primary">
Add Note</button>
</form>
</div>
</div>
</div>
<div class="col-md-6">
{#each notes as note}
<div class="card ">
<div class="card-body">
<h5 class="card-title">{note.title}</h5>
<p class="card-text">{note.content}</p>
<button class="btn btn-info" on:click={editNote()}>Edit</button>
<button class="btn btn-danger" on:click={deleteNote()}>Delete</button>
</div>
</div>
{/each}
</div>
</div>
</div>
</section>
Now lets add some script to make it functional
<script>
let notes = [];
let data = {
title: "",
content: "",
id: null
};
let addNote = () => {
//create functionality
}
let deleteNote = id => {
//delete functionality
};
let editNote = note => {
//editfunctionality
};
let updateNote = () => {
//update functionality
}
I have my note template ready but I need to store the values which I enter. So, I will make use of *bind: *
Now my template would look like this:
<section>
<div class="container">
<div class="row mt-5">
<div class="col-md-6">
<div class="card p-2 shadow">
<div class="card-body">
<h5 class="card-title mb-4">Add New Note</h5>
<form>
<div class="form-group">
<label for="title">Title</label>
<input
bind:value={data.title}
type="text"
class="form-control"
id="text"
placeholder="Note Title" />
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea
class="form-control"
id="content"
bind:value={data.content}
rows="3"
placeholder="Note Content" />
</div>
<button type="submit" on:click|preventDefault={addNote} class="btn btn-primary">
Add Note</button>
</form>
</div>
</div>
</div>
<div class="col-md-6">
{#each notes as note}
<div class="card ">
<div class="card-body">
<h5 class="card-title">{note.title}</h5>
<p class="card-text">{note.content}</p>
<button class="btn btn-info" on:click={editNote()}>Edit</button>
<button class="btn btn-danger" on:click={deleteNote()}>Delete</button>
</div>
</div>
{/each}
</div>
</div>
</div>
</section>
I wanted to experiment this with stores concept. So, I will add writable store to it and add my logic to the store.
Now create a file name Store.js
import { writable } from 'svelte/store';
const store = () => {
const state = []; //Initial state
const {subscribe, set, update} = writable(state);
const tasks= {
createNote(data) {
console.log("data: ", data);
//logic
},
modify() {
//logic
},
delete(id) {
//logic
}
}
return {
subscribe,
set,
update,
...tasks
}
}
export const notesStore = store();
Lets breakdown the above code:
- Create a function named store which would contain crud logic.
- Create an initial state.
- Create an object tasks which would have helper functions like add, delete and modify.
- My store should return default methods of store which are subscribe, set and update and also it should give access to tasks object which holds my helper functions.
- So, we just need to import this in our component and invoke this helper functions on respective event handlers which we would write for our component.
I will update Notes.svelte with following code
<script>
import { notesStore } from './Store.js'; //Import store
let notes = []; //Array used to iterate over number of notes
let data = { // An object to store the entered values
title: "",
content: "",
id: null
};
//Subscription with store for latest changes
const unsubscribe = notesStore.subscribe(value => {notes = value});
let addNote = () => {
const newNote = {
id: notes.length + 1,
title: data.title,
content: data.content
};
notesStore.createNote(newNote); //trigger create functionality
data = {
id: null,
title: "",
content: ""
};
}
let deleteNote = id => {
notesStore.delete(id);
};
let isEdit = false;
let editNote = note => {
isEdit = true;
data = note;
};
let updateNote = () => {
isEdit = !isEdit;
notesStore.modify(data);
data = {
id: null,
title: "",
content: ""
};
}
</script>
<section>
<div class="container">
<div class="row mt-5">
<div class="col-md-6">
<div class="card p-2 shadow">
<div class="card-body">
<h5 class="card-title mb-4">Add New Note</h5>
<form>
<div class="form-group">
<label for="title">Title</label>
<input
bind:value={data.title}
type="text"
class="form-control"
id="text"
placeholder="Note Title" />
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea
class="form-control"
id="content"
bind:value={data.content}
rows="3"
placeholder="Note Content" />
</div>
{#if isEdit === false}
<button type="submit" on:click|preventDefault={addNote} class="btn btn-primary">
Add Note</button>
{:else}
<button type="submit" on:click|preventDefault={updateNote} class="btn btn-info">
Edit Note</button>
{/if}
</form>
</div>
</div>
</div>
<div class="col-md-6">
{#each notes as note}
<div class="card ">
<div class="card-body">
<h5 class="card-title">{note.title}</h5>
<p class="card-text">{note.content}</p>
<button class="btn btn-info" on:click={editNote(note)}>Edit</button>
<button class="btn btn-danger" on:click={deleteNote(note.id)}>Delete</button>
</div>
</div>
{/each}
</div>
</div>
</div>
</section>
My final store logic would look like:
import { writable } from 'svelte/store';
const store = () => {
const state = []
const {subscribe, set, update} = writable(state);
const methods = {
createNote(data) {
console.log("data: ", data);
update(state => {
state = state.concat(data);
console.log("store data: ",state);
return state;
});
},
modify() {
update(state => {
console.log('state in store: ',state);
return state;
});
},
delete(id) {
console.log(id);
update(state => state.filter(state => state.id != id))
}
}
return {
subscribe,
set,
update,
...methods
}
}
export const notesStore = store();
Now move to App.svelte and import Notes.svelte and place in
<script>
import Notes from './Notes.svelte';
</script>
<main>
<p>Visit the <a href="https://svelte.dev/tutorial">Svelte tutorial</a> to learn how to build Svelte apps.</p>
<Notes />
</main>
Now check http://localhost:5000/ and try creating , editing and deleting a note.
As I am still exploring sveltejs, so this might not be the best approach or practice. But I think this can help you to dig more into svelte store.
Hope this helps. Cheers !!!
Top comments (0)