- Lab
-
Libraries: If you want this lab, consider one of these libraries.
- Core Tech
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.
Lab 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 (
.sveltefiles) 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 -- --hostto 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
solutiondirectory. -
-
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/assetsfolder.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
scripttag within theApp.sveltefile.Declare a
snippetsvariable and set it to an empty array. Then declare atitlevariable as an empty string. Following that, declare acodevariable as an empty string. Finally, declare aneditingIndexvariable and set its value to-1.By doing this, you declare and initialize state variables using Svelte's reactive state management.
Essentially,
snippetsis an array that will hold the code snippets,titleandcodeare strings that will hold the current input from the user, andeditingIndexis used to track if the user is editing an existing snippet (-1indicates 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.sveltefile. Add the following pseudo-code within thescripttag.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 keysnippetsfrom the browser's local storage.The
<< 1 >>.getItemmethod returns the value associated with the given key if it exists; otherwise, it returns null. The result is assigned to thesavedSnippetsvariable.<< 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 ifsavedSnippetsis truthy.Since
<< 1 >>.getItemreturns null when the requested key does not exist, this condition effectively checks whether any snippets were previously saved.If
savedSnippetsis 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.svelteand add the following code within thescripttag.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
snippetsarray 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 constantsaveSnippetsthat 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 >>.setItemmethod takes two arguments: the first is the key under which the data should be stored (snippetsin 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
saveSnippetsfunction 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.sveltefile and add anaddSnippetfunction within thescripttag. 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
titleandcodeare not empty.If editing an existing snippet (indicated by
editingIndexbeing 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
snippetto 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
saveSnippetsto persist changes and resetstitleandcodefor the next input.if (title.trim() && code.trim()) { ... }checks that bothtitleandcodeare not empty or just whitespace.if (editingIndex > -1) { ... } else { ... }determines if this is an edit operation (ifeditingIndexis set) or an addition of a new snippet.You must then update the snippet at
editingIndexwith the newtitleandcode, here:<< Do something here... >>On the other hand,
<< Do something else here... >>adds a new snippet to the snippets array.saveSnippets();calls thesaveSnippetsfunction to save the updated snippets to local storage.title = '';andcode = '';resets thetitleandcodevariables, 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.svelteand within thescripttag, add the followingeditSnippetfunction.const editSnippet = (index) => { editingIndex = index; << Access the title property >> << Access the code property >> };This function sets
editingIndexto the index of the snippet to be edited, and assignstitleandcodeto 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
titlevariable.Since
titleis 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
codeof the snippet being edited to thecodevariable, filling in the corresponding input field in the UI with the snippet’s code.The
editSnippetfunction 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.sveltefile and add the following function within thescripttag.<script> const deleteSnippet = (index) => { << Do something here >> saveSnippets(); }; </script>This function removes a snippet from the
snippetsarray based on its index.Within
<< Do something here >>you must use thefiltermethod 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 !== indexto ensure that all snippets except the one to be deleted are included in the new array.*saveSnippets();:This line calls the
saveSnippetsfunction 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
deleteSnippetfunction 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.sveltefile and after the closingscripttag, 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:valuedirective to create a two-way binding between the form inputs and the component's state variables (titleandcode), ensuring the inputs are synchronized with the component's state.The form submission is handled by the
addSnippetfunction, 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|preventDefaultdirective prevents the default form submission behavior (which typically refreshes the page) and instead calls theaddSnippetfunction 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 thetitlevariable in the component's script.This means any change to the input field updates
title, and any programmatic change totitleupdates the input field.You must use a
placeholderattribute 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 thetextareacontent to thecodevariable 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 whethereditingIndexis 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.sveltefile and after theformthat 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
snippetsarray 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
editSnippetwith the snippet's index, filling the form with the snippet's details for editing.The "Delete" button calls
deleteSnippetwith 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
snippetand 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 thesnippetsarray.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 currentsnippetobject.<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.codeis the current snippet’s code.<button on:click={() => editSnippet(index)}>Edit</button>: This button, when clicked, calls theeditSnippetfunction 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 thedeleteSnippetfunction with the currentindexupon a click event, which removes the snippet from thesnippetsarray 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.sveltefile add the following code before the closingscripttag.onMount(loadSnippets);Add the following code after the other two import statements.
<< Import onMount >>This code uses Svelte's
onMountlifecycle function to callloadSnippetswhen 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:
onMountis called with a function as its argument. The function you pass toonMountwill be executed as soon as the component has been inserted into the DOM.It's important to note that
onMountis 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
loadSnippetsare 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
loadSnippetsis called withinonMountrather 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.sveltefile, 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.svelteorfinal.sveltecode against theApp.sveltecode you wrote.Well done for following along this guided lab. You've done a great job.
About the author
Real skill practice before real-world application
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.
Learn by doing
Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.
Follow your guide
All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.
Turn time into mastery
On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.