|

Node.js Todo List Tutorial

nodejs todo tutorial

In this Node.js adventure, we will tackle the obligatory todo list application. Along the way we are going to learn about the basics of modules and how to use them in a Node environment. After that, we’ll explore how to use require() to make use of both our own files in addition to third party modules created by the community. We will need to see how to accept user input as well as make use of JSON to store the data that makes up our todo items. Let’s start getting our Node.js todo list application up and running now.


Run a JavaScript File as a NodeJS application

We learned already how to type some commands into the Node console and make some things happen. Now, we want to actually create JavaScript files that can be run as a Node.js application. How can we do this? We will start with the obligatory Hello World example. First up, we will create a directory on our machine to hold some JavaScript files.

C:\>mkdir node

Now, we will open that folder using Visual Studio Code, a fantastic and powerful code editor that also happens to be free! Once open, go ahead and create a new file of app.js like so.
new file visual studio code

In the app.js file, we will add some code and save the file if needed. (Visual studio code will auto save for you in most cases)
hello world node js

You now have a bare bones Node.js application that is ready to run. I know you can barely contain your excitement. We can now run that program!
hellow world in node

Savage! I know it seems trivial, but you just went through the basic steps of how to create a very basic Node.js application. We created a directory to store our program files, added some code, and finally ran the program. That’s pretty much it! Even the biggest, most complex applications will start with these first simple steps.


Module Basics In Node.js

With our hello world example tackled, let’s learn a little bit about modules in Node.js. Modules are units of functionality. In Node there are all kinds of modules you can make use of. Some help you work with the filesystem, others may provide http services or DNS services.


require() for built in modules

Let’s see how we can make use of a module in Node.js. Consider this code.

In this code, we first make use of the node require() function. It is used to require modules in Node. The ‘fs’ string that we pass to require() loads in the built in file system module of Node. This is stored in the fs object, which now has a wealth of methods you can make use of. For this quick example, we will simply make use of the fs.appendFile() method which asynchronously appends data to a file, creating the file if it does not yet exist. The first argument is the name of the file to write to. We provide ‘file.txt’ as the file. The next argument is the data to be written to that file. Lastly, we must include a callback to handle any errors that might occur. Before we run the program, here is what visual studio code looks like.
node requirefs

Now we can run the application from the command line by typing node app.js.

C:\node>node app.js
Data has been written to file.txt
null

After the program finishes, notice that we now have a new file in our editor of file.txt. This is because Node.js just created the new file and wrote data to it. Pretty cool!
file written by nodejs

Go ahead and run the program one more time, and you will see that a second set of data gets appended to the file.
writing to the file system

If you’re so inclined, you could run this program 500 times and store the text of “Writing To The Filesystem!” 500 times in that file.txt text file. Of course that doesn’t really make sense, but now we have a real working example of requiring the fs module into a Node application and writing data to the file system. Excellent!


require() for your own modules or files

With Node and ES6, it is very easy to put code into separate files and then import them as needed. This drastically cleans up your code base and helps to keep everything organized in a very neat manner for your projects. Sometimes I think simple code organization is literally half the battle in software engineering. So in spirit of the todo list application, let’s create a new todos.js file in our editor and place the following code in it.


todos.js

Here we are exporting the addTodo() arrow function. We simply add a console statement to the file to show when this file runs during the application execution. Now check this out. In the main app.js file, we can now require what has been exported from todos.js.

Running the application shows us that everything is working great.
require your own js files

Most times the goal of exports is to be able to export functions which get used in the main app.js file.


Requiring 3rd Party Modules into your node app

Now we want to make use of the best thing about Node.js. All of the wonderful software that has already been written for you! In order to make use of 3rd party modules, we first need to create a package.json file. We can easily do this by running the npm init command in the project root.

c:\node>npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See npm help json for definitive documentation on these fields
and exactly what they do.

Use npm install  --save afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (node)

As you can see, it begins a bit of a shell program where we are presented with various questions about the application you are building. Here is how we filled out this little questionnaire.

name: (node) todos-node
version: (1.0.0)
description:
entry point: (app.js)
test command:
git repository:
keywords:
author: vegibit
license: (ISC)
About to write to c:\node\package.json:

{
  "name": "todos-node",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "dependencies": {},
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "vegibit",
  "license": "ISC"
}


Is this ok? (yes) yes

c:\node>

We now have a package.json file in our project. With this file in place, we can start adding 3rd party modules to our application. We will start by adding the popular JavaScript utility library Lodash by typing the following at the command prompt.

c:\node>npm install lodash --save

This command will do a couple of things for you. First off, it will now update your package.json file automatically for you with the dependency you just added. Second, the NPM software will reach out to the servers and grab the software you want to use, and place it on your machine in a new directory called node_modules. Check it out!
npm install lodash


Lodash can now be used in your project

We can update our main app.js file to pull in Lodash now.


app.js

Bingo! That’s all it takes to download and install a 3rd party module into your Node.js project. You have well over Six Hundred Thousand(!) to choose from, so have fun.


Restarting Your Node.js App With nodemon

As you build your application, you are going to need to continuously go back and manually run the application from the terminal. That’s not really any fun, and we can and should automate all the things! To have our application automatically re initialize after we make changes to our JavaScript files, we can install the popular nodemon module to do this for us. Let’s go ahead and add nodemon to our machine.

c:\node>npm install nodemon -g

Once nodemon is installed, you can now run your applications by typing nodemon <filename> instead of node <filename>. Have a look.
running nodemon

What is happening now is that nodemon has put the application in a running state, but it is always monitoring for any changes. If those changes are detected, the appliation will automatically relaunch and you can watch it in real time at the terminal. Let’s make a change to one of our application files. We’ll just add a simple logging statement to app.js like so.

If you head on over to the terminal, have a look at what we see!

[nodemon] restarting due to changes...
[nodemon] starting node app.js
[nodemon] restarting due to changes...
Running app.js
Running todos.js
New Todo created.
We Love Nodemon!
[nodemon] starting node app.js
Running app.js
Running todos.js
New Todo created.
We Love Nodemon!
[nodemon] clean exit - waiting for changes before restart

Nodemon detected any changes right away and restarted the application. You are going to love this convenience as you develop applications in Node.js.


Fetching User Input

Now we finally get to fetch some input from the user. This is how we will be able to add a todo item to the application. We just want to set up something super basic. We want the user to be able to type in a todo, or reminder into the system. We will make use of a Node.js module named Yargs to help us with this. Let’s install Yargs first.

c:\node>npm install yargs --save

Once that installs, we can require it in our application as we see here.

Now we will make a couple of additions here.

In the above code, we are collecting any command line arguments provided via yargs.argv and storing that in args. Then, we are going to log out an argument of ‘todo’ by accessing it with args.to. Let’s see that in action.
yargs command line input

As we can see if we run app.js and pass some arguments like we did here, we can then access them inside the program. By typing node app.js --todo="eat lunch", we are running app.js and passing in an argument of todo and it’s value is eat lunch.

We are going to want to addTodo, listTodos, readTodo, or deleteTodo. We will need to capture more information from the command line to do that. We can capture input that way like so:

c:\node>node app.js addTodo
Running app.js
Running todos.js
You ran the command: addTodo

c:\node>node app.js listTodos
Running app.js
Running todos.js
You ran the command: listTodos

c:\node>node app.js readTodo
Running app.js
Running todos.js
You ran the command: readTodo

c:\node>node app.js deleteTodo
Running app.js
Running todos.js
You ran the command: deleteTodo

By simply including the name of the command after we initialize app.js, we can see that we have captured that input and we are outputting it to the console.


Using JSON To Manage Data

We need to have a way to store those todo items in our application so they don’t just float off into the abyss. We can do this with JSON. We can start by setting up a way to add a todo item.


Adding a Todo

First off, let’s update the app.js file like so.

Now we need to add some logic to the todos.js file to actually add an item to a JSON data object.

Ok, I think we can run the program. Here goes:

c:\node>node app.js addTodo --title="Mow the lawn"
Running app.js
Starting todos.js
Running Command:  addTodo

If you look in Visual Studio Code, you’ll see a new file there. Inspecting that file shows us that the todo we just added to the system is now stored in that todos-data.json file. Cool!
data stored to json file

We’ll add a few more items.

c:\node>node app.js addTodo --title="Go to work"
Running app.js
Starting todos.js
Running Command:  addTodo

c:\node>node app.js addTodo --title="Read the paper"
Running app.js
Starting todos.js
Running Command:  addTodo

c:\node>node app.js addTodo --title="Netflix and chill"
Running app.js
Starting todos.js
Running Command:  addTodo

Sure enough, our json data file is updating.

The functions that are doing the heavy lifting for us are as follows.


readFileSync

Synchronously reads the entire contents of a file.

  • @param path
    A path to a file. If a URL is provided, it must use the file: protocol. URL support is experimental. If a file descriptor is provided, the underlying file will not be closed automatically.
  • @param options — An object that may contain an optional flag. If a flag is not provided, it defaults to ‘r’.

JSON.parse

Converts a JavaScript Object Notation (JSON) string into an object.

  • @param text — A valid JSON string.
  • @param reviver
    A function that transforms the results. This function is called for each member of the object. If a member contains nested objects, the nested objects are transformed before the parent object is.

writeFileSync

Synchronously writes data to a file, replacing the file if it already exists.

  • @param path
    A path to a file. If a URL is provided, it must use the file: protocol. URL support is experimental. If a file descriptor is provided, the underlying file will not be closed automatically.
  • @param data — The data to write. If something other than a Buffer or Uint8Array is provided, the value is coerced to a string.
  • @param options
    Either the encoding for the file, or an object optionally specifying the encoding, file mode, and flag. If encoding is not supplied, the default of ‘utf8’ is used. If mode is not supplied, the default of 0o666 is used. If mode is a string, it is parsed as an octal integer. If flag is not supplied, the default of ‘w’ is used.

JSON.stringify

Converts a JavaScript value to a JavaScript Object Notation (JSON) string.

  • @param value — A JavaScript value, usually an object or array, to be converted.
  • @param replacer — A function that transforms the results.
  • @param space — Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.

Deleting a Todo Item

Now let’s add the logic to delete a todo item from the JSON data store. Our updated todos.js and app.js files are below.
todos.js

app.js

We can now run the program passing a title that we know exists, and one that does not to confirm it all works correctly.

c:\node>node app.js deleteTodo --title="Netflix and chill"
Running app.js
Starting todos.js
Running Command:  deleteTodo
Todo was deleted

c:\node>node app.js deleteTodo --title="Watch Pulp Fiction"
Running app.js
Starting todos.js
Running Command:  deleteTodo
Todo not found

Reading a Todo Item

This iteration will add the ability to simply read a todo item when we pass in the title of that todo item.
app.js

todos.js

Let’s test it out! It looks like it is working!

c:\node>node app.js readTodo --title="Mow the lawn"
Running app.js
Starting todos.js
Running Command:  readTodo
Great! The todo was found.
------
It's title is: Mow the lawn

c:\node>node app.js readTodo --title="Netflix and chill"
Running app.js
Starting todos.js
Running Command:  readTodo
Whoops! The todo was not found.

Listing All Todo Items

Last up, we want the ability to list all todo items from the application. Have a look at the final iteration of todos.js and app.js that add support for this.
todos.js

app.js

Once again we can run the application and test this new command. Looking good!

c:\node>node app.js listTodos
Running app.js
Starting todos.js
Running Command:  listTodos
Printing 3 todo(s).
------
It's title is: Mow the lawn
------
It's title is: Go to work
------
It's title is: Read the paper

Node.js Todo List Tutorial

While this tutorial application is not going to change the course of software development, it was in fact a great introduction to how we can build applications in Node.js. We were able to set up a nice little application that can create, read, list, and delete items from a JSON data store. We saw how to use our own custom JavaScript files, as well as 3rd party modules. This is a great start and we’ll be looking at more advanced Node.js tutorials soon!

|