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)