- Lab
- Core Tech
![Labs Labs](/etc.clientlibs/ps/clientlibs/clientlib-site/resources/images/labs/lab-icon.png)
Guided: Build a Code Snippet Manager in Svelte
In this guided lab, you'll be building a dynamic code snippet manager. You'll dive into Svelte's component-based architecture, crafting an interactive interface with ease. You'll discover the power of Svelte's reactive state management, allowing you to handle app states, and harness Svelte's simplicity of form handling, seamlessly capturing user input. Finally, you'll learn about local storage in JavaScript, enabling your app to persist data across browser sessions.
![Labs Labs](/etc.clientlibs/ps/clientlibs/clientlib-site/resources/images/labs/lab-icon.png)
Path Info
Table of Contents
-
Challenge
Understanding Svelte Basics
Welcome to this guided lab. You will be building a Code Snippet Manager in Svelte, but first, let's talk about the fundamental concepts of Svelte and how it facilitates building reactive web applications.
Svelte is a modern JavaScript framework for building user interfaces. Unlike other frameworks that do a lot of work in the browser, Svelte shifts that work into a compile step that happens when you build your app, resulting in highly optimized vanilla JavaScript.
The core philosophy behind Svelte is to write less code, with its reactive updates model being straightforward and intuitive.
Svelte applications are composed of components, which are encapsulated parts of your application that manage their state and presentation. Components are typically written in single-file components (
.svelte
files) that include HTML, JavaScript, and CSS.Svelte is gaining popularity for a few reasons:
-
Ease of Learning: With less boilerplate and a straightforward approach, Svelte is easier to grasp for beginners.
-
Performance: Due to compile-time optimizations, Svelte applications can be more performant, especially for smaller projects.
-
Readability and Maintenance: Svelte's syntax is clean and easy to understand, promoting maintainability.
Because this environment does not have internet access this project has already been scaffolded for you using Vite, required assets have been downloaded, and unneeded files have been removed. (Picnic CSS) has also been added to provide basic styling of native HTML elements.
In the terminal, run
npm run dev -- --host
to start the dev server. The application will be available with hot module replacement by clicking on the Web Browser tab, and clicking the Open in new browser tab icon, or you can open a new browser tab by clicking the following link: {{localhost:5173}}.info> The solution for each task in this lab are available for your reference in the
solution
directory. -
-
Challenge
Setting Up the Component and Styles
Start by setting up the component and importing necessary CSS files and JavaScript modules.
You'll need to import two CSS files into your Svelte component. These files can be found under the
src/assets
folder.The first line must import a CSS framework (
picnic.min.css
) for styling, and the second line imports custom styles (style.css
) specific to this component.This setup is crucial for ensuring that the styles are applied to the component when it renders. The next step is to initialize the state variables for the Code Snippet Manager application.
You must add specific variables to the
script
tag within theApp.svelte
file.Declare a
snippets
variable and set it to an empty array. Then declare atitle
variable as an empty string. Following that, declare acode
variable as an empty string. Finally, declare aneditingIndex
variable and set its value to-1
.By doing this, you declare and initialize state variables using Svelte's reactive state management.
Essentially,
snippets
is an array that will hold the code snippets,title
andcode
are strings that will hold the current input from the user, andeditingIndex
is used to track if the user is editing an existing snippet (-1
indicates no snippet is being edited). -
Challenge
Managing Snippets
Throughout this step, there are two things you must accomplish:
-
Write a function to load snippets from local storage.
-
Save Snippets to Local Storage. Now, you are going to write a function to load snippets from local storage.
Open the
App.svelte
file. Add the following pseudo-code within thescript
tag.const loadSnippets = () => { const savedSnippets = << 1 >>.getItem('snippets'); if (savedSnippets) { snippets = JSON.<< 2 >>(savedSnippets); } };
You must replace
<< 1 >>
and<< 2 >>
.So,
<< 1 >>
represents the local storage and<< 2 >>
indicates the action of parsing the value ofsavedSnippets
.This function checks local storage for saved snippets using
<< 1 >>.getItem('snippets')
.If there are saved snippets, it parses them from JSON into the snippets array, making them available in the component's state for rendering.
This function is designed to retrieve a list of saved code snippets from the browser's local storage and load them into the application's state.
The function makes use of the Web Storage API, specifically the local storage object, to persist data across browser sessions for a specific domain.
const loadSnippets = () => { ... };
defines a function using arrow function syntax and assigns it to the constantloadSnippets
. This syntax is a concise way to write functions in JavaScript. The function can be called later in the code by referencing its name,loadSnippets()
.const savedSnippets = << 1 >>.getItem('snippets');
attempts to retrieve the item with the keysnippets
from the browser's local storage.The
<< 1 >>.getItem
method returns the value associated with the given key if it exists; otherwise, it returns null. The result is assigned to thesavedSnippets
variable.<< 1 >>
is a key-value storage that allows web applications to store data persistently in the browser.Each item stored in
<< 1 >>
persists across browser sessions until explicitly deleted. Values are stored as strings.if (savedSnippets) { ... }
checks ifsavedSnippets
is truthy.Since
<< 1 >>.getItem
returns null when the requested key does not exist, this condition effectively checks whether any snippets were previously saved.If
savedSnippets
is not null (meaning some snippets were found), the block of code inside the if statement is executed.snippets = JSON.<< 2 >>(savedSnippets);
parses the string retrieved from local storage into a JavaScript object or array.The
JSON.<< 2 >>
method is used because data is stored in local storage as a string, but the application needs to work with the data as a JavaScript object or array.This line assumes that the saved snippets are stored in JSON format (a common practice for serializing complex data structures for storage).
After parsing, the resulting object or array is assigned to the snippets variable, effectively loading the saved snippets into the application's state. Next, you must implement a function to save the current state of snippets to local storage. You can name this function
saveSnippets
.Open the
App.svelte
and add the following code within thescript
tag.const saveSnippets = () => { << 1 >>.setItem('snippets', JSON.<< 2 >>(snippets)); };
<< 1 >>
represents the local storage object.<< 2 >>
represents the operation to convert into a string representation a JSON value.This function serializes the
snippets
array to a JSON string and saves it in local storage.This ensures that the snippets are persisted between page reloads or when closing and reopening the browser.
This function is designed to save the current state of the snippets array to the browser's local storage.
It achieves this by serializing the snippets array into a JSON string and then storing it with the key
snippets
.const saveSnippets = () => { ... };
creates a new constantsaveSnippets
that stores the function. This function can be invoked later in the code by callingsaveSnippets()
. The use of arrow function syntax provides a concise way to define the function.JSON.<< 2 >>(snippets)
converts the snippets array into a JSON string. TheJSON.<< 2 >>
method is used for serializing JavaScript objects or arrays into a string format.This is necessary because the Web Storage API (which includes local storage) only supports storing data as strings.
Serializing the array allows complex data structures like objects or arrays to be stored as a text representation.
<< 1 >>.setItem('snippets', JSON.<< 2 >>(snippets));
stores the serialized snippets array in the browser's local storage under the keysnippets
.The
<< 1 >>.setItem
method takes two arguments: the first is the key under which the data should be stored (snippets
in this case), and the second is the data to store (the JSON string representation of the snippets array).Once this method is executed, the snippets data is persisted in the browser's local storage, making it available across browser sessions and reloads.
The
saveSnippets
function is crucial for web applications that need to persist data locally on the user's device.By storing data in local storage, the application can remember the user's data even after the browser is closed or the page is reloaded.
This function, in particular, allows the application to save the current state of code snippets, ensuring that user-generated content is not lost between sessions.
-
-
Challenge
Adding, Editing, and Deleting Snippets
It's time to look at how you can implement Adding, Editing, and Deleting Snippets.
You will do this in three stages:
- Adding a New Snippet
- Editing a Snippet
- Deleting a Snippet You must create a function to add a new snippet or update an existing one.
Open the
App.svelte
file and add anaddSnippet
function within thescript
tag. The function's pseudo-code is as follows.const addSnippet = () => { if (title.trim() && code.trim()) { if (editingIndex > -1) { << Do something here... >> } else { << Do something else here... >> } saveSnippets(); title = ''; code = ''; } };
This function first checks if both
title
andcode
are not empty.If editing an existing snippet (indicated by
editingIndex
being non-negative), it updates the snippet at the given index. Which is what you must do in the following section:<< Do something here... >>
Otherwise, it adds a new
snippet
to the end of the snippets array. Which is what you must do in the following section:<< Do something else here... >>
After adding or updating, it calls
saveSnippets
to persist changes and resetstitle
andcode
for the next input.if (title.trim() && code.trim()) { ... }
checks that bothtitle
andcode
are not empty or just whitespace.if (editingIndex > -1) { ... } else { ... }
determines if this is an edit operation (ifeditingIndex
is set) or an addition of a new snippet.You must then update the snippet at
editingIndex
with the newtitle
andcode
, here:<< Do something here... >>
On the other hand,
<< Do something else here... >>
adds a new snippet to the snippets array.saveSnippets();
calls thesaveSnippets
function to save the updated snippets to local storage.title = '';
andcode = '';
resets thetitle
andcode
variables, clearing the form inputs.This function is integral to the functionality of a code snippet manager, allowing users to seamlessly add new snippets or update existing ones while ensuring that their changes are saved across browser sessions. Your objective is to enable snippet editing by filling the form with the snippet's current details.
To do that you must open
App.svelte
and within thescript
tag, add the followingeditSnippet
function.const editSnippet = (index) => { editingIndex = index; << Access the title property >> << Access the code property >> };
This function sets
editingIndex
to the index of the snippet to be edited, and assignstitle
andcode
to the values of the snippet, allowing the user to see and modify the existing snippet details in the form.editingIndex = index;
:This line marks which snippet is currently being edited by assigning its array index to
editingIndex
.This is crucial for the add/update logic to correctly update this snippet instead of creating a new one.
<< Access the title property >>
:This line assigns the title of the snippet being edited to the
title
variable.Since
title
is likely bound to an input field in the UI, this action automatically populates that field with the snippet’s title.<< Access the code property >>
:Similar to the previous line, this assigns the
code
of the snippet being edited to thecode
variable, filling in the corresponding input field in the UI with the snippet’s code.The
editSnippet
function is integral for enabling the edit functionality within a snippet manager application.By setting the editing context and populating the form with the snippet's current content, it provides a seamless user experience for editing snippets. Next, you must implement a function to delete a snippet.
So, open the
App.svelte
file and add the following function within thescript
tag.<script> const deleteSnippet = (index) => { << Do something here >> saveSnippets(); }; </script>
This function removes a snippet from the
snippets
array based on its index.Within
<< Do something here >>
you must use thefilter
method to create a new array excluding the snippet at the given index, then saves the updated list to local storage.<< Do something here >>
:This line creates a new snippets array excluding the snippet at the given
index
. The is a placeholder for the element value, which is not used in the condition.You must use a condition
i !== index
to ensure that all snippets except the one to be deleted are included in the new array.*saveSnippets();
:This line calls the
saveSnippets
function to persist the updated list of snippets to local storage.This is crucial for maintaining the integrity of the snippet collection across different sessions.
The
deleteSnippet
function plays a vital role in managing the lifecycle of snippets within the application, allowing users to remove snippets they no longer need. -
Challenge
User Interface and Interaction
Now, you will explore how to create the form for adding and editing snippets.
You will do this in two separate tasks:
-
Construct a form in HTML that allows users to input a title and code for a snippet.
-
Display Snippets and Provide Edit and Delete Options. In this task, you must construct a form in HTML that allows users to input a title and code for a snippet.
To do that, open the
App.svelte
file and after the closingscript
tag, let's add the following code.<h1>Code Snippet Manager</h1> <div class="snippet-container"> <form on:submit|preventDefault={addSnippet}> <label>Title: << Add the Title Input Field here >> </label> <label>Code: << Add the Code Input Field here >> </label> << Add the Submit button here >> </form> </div>
Please make sure you use the correct spacing and indentation
This HTML structure creates a user interface for the snippet manager. It includes a form with two fields: one for the snippet's title and another for the code.
You must use the
bind:value
directive to create a two-way binding between the form inputs and the component's state variables (title
andcode
), ensuring the inputs are synchronized with the component's state.The form submission is handled by the
addSnippet
function, and the button label dynamically changes based on whether the user is adding a new snippet or updating an existing one.<h1>Code Snippet Manager</h1>
: This line creates a heading (H1) for the application, serving as the title of the page or section. It indicates the purpose of the application to the user.<div class="snippet-container">...</div>
encloses the form used for inputting snippet details.The
class="snippet-container"
attribute applies specific styling to this div, which could include padding, margins, backgrounds, etc., to visually distinguish or organize the layout.<form on:submit|preventDefault={addSnippet}>...</form>
defines a form with an event handler for the submit event.The
on:submit|preventDefault
directive prevents the default form submission behavior (which typically refreshes the page) and instead calls theaddSnippet
function when the form is submitted.This function handles adding a new snippet or updating an existing one based on the state of
editingIndex
.<< Add the Title Input Field here >>
: This line creates a labeled input field for entering the title of the snippet.You must use the
bind:value={title}
directive to creates a two-way binding between the input's value and thetitle
variable in the component's script.This means any change to the input field updates
title
, and any programmatic change totitle
updates the input field.You must use a
placeholder
attribute to provide a greyed-out text inside the input box, guiding the user on what to enter.<< Add the Code Input Field here >>
: Similar to the title input but for the snippet’s code.Here, you should use a
textarea
, which is used instead of an input to accommodate multi-line text input, allowing users to paste or type in code snippets.You must also a
bind:value={code}
directive to bind thetextarea
content to thecode
variable in the script.<< Add the Submit button here >>
: Here, you must define a button for submitting the form. The button's label dynamically changes between "Update Snippet" and "Add Snippet" depending on whethereditingIndex
is greater than-1
(indicating an edit operation) or not.This provides contextual feedback to the user about the action that will be performed upon clicking the button.
This code snippet effectively creates a user interface for managing code snippets, allowing users to add new snippets or edit existing ones within the same form.
The use of Svelte's reactive bindings and event handling makes the form interactive and directly tied to the application's state, providing a seamless user experience. Now, you must go ahead and display each snippet with options to edit or delete.
To do that, open the
App.svelte
file and after theform
that was added in the previous task, add the following code.<ul> << Iterate through code snippet items >> <li> <strong>{snippet.title}</strong> <pre>{snippet.code}</pre> <button on:click={() => editSnippet(index)}>Edit</button> <button on:click={() => deleteSnippet(index)}>Delete</button> </li> {/each} </ul>
Please make sure you use the correct spacing and indentation
This code iterates over the
snippets
array and renders each snippet in a list.For each snippet, it displays the title and code, and provides "Edit" and "Delete" buttons.
The "Edit" button calls
editSnippet
with the snippet's index, filling the form with the snippet's details for editing.The "Delete" button calls
deleteSnippet
with the index, removing the snippet from the list.<< Iterate through code snippet items >>
: Here, you must use a directive to iterate over the snippets array, rendering a list item (<li>
) for each snippet.For each iteration, you must assign the current snippet to a temporary variable
snippet
and the current index toindex
.You must use
(snippet.title)
, which is the part that is a key expression that helps Svelte identify each list item uniquely, optimizing the reactivity system for updates, additions, or deletions in thesnippets
array.This is particularly useful for performance and preventing unnecessary DOM updates.
<strong>{snippet.title}</strong>
: For each snippet, the title is displayed in bold using the<strong>
tag. The title is accessed from the currentsnippet
object.<pre>{snippet.code}</pre>
: The code of the snippet is wrapped in a<pre>
tag, which is used to display preformatted text.This ensures that the code’s formatting and spacing are preserved in the display. The
snippet.code
is the current snippet’s code.<button on:click={() => editSnippet(index)}>Edit</button>
: This button, when clicked, calls theeditSnippet
function and passes the current index of the snippet.The function is responsible for setting up the application state for editing the selected snippet, typically by populating form fields with the snippet’s title and code for editing.
<button on:click={() => deleteSnippet(index)}>Delete</button>
: Similarly, this button invokes thedeleteSnippet
function with the currentindex
upon a click event, which removes the snippet from thesnippets
array and updates the list. -
-
Challenge
Initialization and Reactivity
The last step required to finish off the Code Snippet Manager, is to initialize and make the app reactive. Next, you must ensure that snippets are loaded when the component mounts and react to changes.
Within the
App.svelte
file add the following code before the closingscript
tag.onMount(loadSnippets);
Add the following code after the other two import statements.
<< Import onMount >>
This code uses Svelte's
onMount
lifecycle function to callloadSnippets
when the component is first rendered.onMount
: This is a lifecycle function provided by Svelte that runs after the component is first rendered and attached to the document's DOM.It's a perfect place to run initialization code, such as fetching data, adding event listeners, or in this case, loading saved snippets from local storage.
Usage:
onMount
is called with a function as its argument. The function you pass toonMount
will be executed as soon as the component has been inserted into the DOM.It's important to note that
onMount
is asynchronous and can return a cleanup function that will be called when the component is destroyed, although that's not being used in this particular case.loadSnippets
: This function's role, as suggested by its name, is to load snippet data.Although the specifics of
loadSnippets
are not provided in the context, based on common patterns, it likely retrieves data from local storage (or another persistence layer), and initializes the component's state with this data, making the snippets available for display or further manipulation in the component.The reason
loadSnippets
is called withinonMount
rather than directly in the script body is to ensure that the component is fully mounted in the DOM before attempting to load and display the snippets.This can be particularly important for operations that may require DOM manipulation or the existence of child components that are also being dynamically loaded or rendered based on the fetched data.
-
Challenge
Completion
By following these steps and tasks, you will have recreated the functionality of the provided
App.svelte
file, learning about Svelte's capabilities for reactive state management, component lifecycle, and user interaction along the way.To make sure you've done things right, feel free to compare the
step06_task01.svelte
orfinal.svelte
code against theApp.svelte
code you wrote.Well done for following along this guided lab. You've done a great job.
What's a lab?
Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.
Provided environment for hands-on practice
We will provide the credentials and environment necessary for you to practice right within your browser.
Guided walkthrough
Follow along with the author’s guided walkthrough and build something new in your provided environment!
Did you know?
On average, you retain 75% more of your learning if you get time for practice.