Create a Todo app with jQuery and localStorage

Create a Todo app with jQuery and localStorage

Welcome back, in this post, we are going to create a todo app with jQuery and localStorage of the browser.

To check the live app that I've created, here is the link to the app. It is a Progressive Web App so you can also install it on your device and use it as a native app.

All of our todo items will be stored in the local storage of our browser and we'll load the todos from the browser every time we'll load our app.

This will eliminate the use of a database for storing our todos and you can read more about local storage here.

Window.localStorage

Now, let's create the basic HTML structure of our todo app.

Create an index.html file in the root directory of your project. Here is the HTML code for our todo app.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Todo by Pratik</title>
    <link rel="stylesheet" href="style.css">
    <meta name="description" content="Offline Todo app, use on the go. No need of internet connectivity. Todo by Pratik is the best todo app you'll need.">
    <link rel="shortcut icon" href="./img/todo.png" type="image/x-icon">
    <link rel="manifest" href="./manifest.json">
  </head>
  <body>
    <div class="main">
      <h1>Todo by <a href="https://pratiksah.com">Pratik</a></h1>
      <input type="text" placeholder="Type and press Enter &#8594;" id="todo" />
      <p class="text-info">Tap on todo to remove them.</p>
      <div class="container">
        <!-- incomplete todo -->
        <div class="incomplete"></div>
      </div>
    </div>
    <!-- link to jq and external js -->
    <script
      src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="./app.js"></script>
  </body>
</html>

Here, I've used jQuery and an external js file for handling all the logic for our app.

Now, to style our app, we are using some custom CSS.

Create a new style.css file in the root directory and paste the below code.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  padding: 80px 20px;
}

.main {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
    Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
  width: 40vw;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  color: rgb(58, 58, 58);
}

a {
  color: rgb(100, 100, 100);
  text-decoration: none;
}

input {
  margin-top: 30px;
  padding: 15px;
  font-size: 22px;
  margin-bottom: 20px;
  border-radius: 4px;
  border: 1px solid rgb(58, 58, 58);
  color: rgb(58, 58, 58);
}

.text-info {
  margin: 0px 0px 10px 0px;
  color: rgb(117, 117, 117);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}

.card {
  width: 100%;
  padding: 15px;
  background-color: rgb(58, 58, 58);
  color: white;
  margin-bottom: 10px;
  border-radius: 4px;
  align-items: center;
}
.card:hover {
  background-color: rgb(121, 119, 119);
  cursor: pointer;
}

::-webkit-scrollbar {
  width: 10px;
}

::-webkit-scrollbar-thumb {
  background:  rgb(92, 91, 91);
}


@media screen and (max-width: 768px) {
  body {
    padding: 10px 20px;
    margin: 0;
  }
  .main {
    width: 80vw;
    margin-top: 30px;
  }
}

Now, this code will help you in styling your app and it will also make your app responsive as I've also used media query.

Let's create our app.js file inside the root directory and we'll write all of our logic in jQuery here.

We'll start by checking the data from the localStorage of the browser whenever our app will load.

To store any data in the localStorage, we use localStorage.setItem('name', 'Pratik');

This will create a key named name and the value of this key will be Pratik.

Now, to get the data, we can use localStorage.getItem('name') and this will return us with the value stored in that key-value pair.

If no key is available with that name, this will return us null.

Now, we'll use the same logic to check for our previous todos stored in the localStorage and if exists, we'll fetch the data from the localStorage and load it in the div with class card.

checkTodos();

// check for data in localStorage

function checkTodos() {
  // todos in the key of my localStorage
  let dataInLocalStorage = localStorage.getItem("todos");
  // check if it is null or not
  if (dataInLocalStorage == null) {
    todos = [];
  } else {
    todos = JSON.parse(dataInLocalStorage);
  }
  let html = "";
  todos.forEach((todo, index) => {
    html += `<div class='card' onclick='removeTodo(${index});'>${todo}</div>`;
  });
  $(".incomplete").empty().append(html);
}

Next, we'll write the logic to add todos and save them in the localStorage.

// adding items in todos

$("input").on("keypress", (e) => {
  if (e.which === 13 && $("input").val() !== "") {
    todo = $("input").val();
    let todosData = localStorage.getItem("todos");
    if (todosData == null) {
      todos = [];
    } else {
      todos = JSON.parse(todosData);
    }
    todos.push(todo);
    localStorage.setItem("todos", JSON.stringify(todos));
    $("input").val("");
    checkTodos();
  }
});

Here, you can see that I've also called the checkTodos() function to update the UI once a new todo is added.

Now, the final code to remove the todo from the localStorage and from the UI.

// logic for removing todo from the todos list

let removeTodo = (index) => {
  let todosData = localStorage.getItem("todos");
  todos = JSON.parse(todosData);
  todos.splice(index, 1);
  localStorage.setItem("todos", JSON.stringify(todos));
  checkTodos();
};

Here, I've created an arrow function for removing the items from the todo. This will also remove the item from the localStorage and it will then update the localStorage with the new data.

The removeTodo() function will be called whenever we'll tap on any of our todo items.

Now, here is the complete code of app.js of the todo app.

checkTodos();

// check for data in localStorage

function checkTodos() {
  // todos in the key of my localStorage
  let dataInLocalStorage = localStorage.getItem("todos");
  // check if it is null or not
  if (dataInLocalStorage == null) {
    todos = [];
  } else {
    todos = JSON.parse(dataInLocalStorage);
  }
  let html = "";
  todos.forEach((todo, index) => {
    html += `<div class='card' onclick='removeTodo(${index});'>${todo}</div>`;
  });
  $(".incomplete").empty().append(html);
}

// adding items in todos

$("input").on("keypress", (e) => {
  if (e.which === 13 && $("input").val() !== "") {
    todo = $("input").val();
    let todosData = localStorage.getItem("todos");
    if (todosData == null) {
      todos = [];
    } else {
      todos = JSON.parse(todosData);
    }
    todos.push(todo);
    localStorage.setItem("todos", JSON.stringify(todos));
    $("input").val("");
    checkTodos();
  }
});

// logic for removing from the todos list
let removeTodo = (index) => {
  let todosData = localStorage.getItem("todos");
  todos = JSON.parse(todosData);
  todos.splice(index, 1);
  localStorage.setItem("todos", JSON.stringify(todos));
  checkTodos();
};

Now, you are done with the coding part and you can now start using it.

Well, this was all for today's post and if you found it helpful, please leave a like & comment below and in my next post, we'll see how you can deploy your static web app for free on Netlify.

I'll be deploying this todo app on netlify and you can also add a domain name there for free.

Thanks for your time and I'll meet you in my next post. Take care and happy coding🙂!

Did you find this article valuable?

Support Pratik Sah by becoming a sponsor. Any amount is appreciated!