đź–± Building a Functional Web App With a Graphical Interface Using Node and Restful API

Alessandro Marchesin
7 min readMay 26, 2023

In our previous article, we explored the process of building a RESTful API with Node, which provided functionalities like authentication, account creation, website checks, and updates. However, it lacked a user-friendly graphical interface for non-developers. In this article, we will delve into the steps required to create a functional design for hosting all these features. By following along, you’ll discover that building a graphical interface for your Node application can be relatively straightforward.

In particular, the steps we will go through are the following:

  1. We will create static HTML pages to render.
  2. We will implement some new helper functions to help us manage
  3. We will improve our routing to handle the requests for the different pages
  4. We’ll enhance app.js to manage client-side requests.
  5. We will add logic to handle the interaction of the user.

As suggested last time, I recommend following along with the code in the repository since it would be impossible to go through each line, and neither is the article’s purpose. Instead, it’s a way to let you know how to handle a UI shell for the node application with real-life examples.

You can find the repository on my GitHub.

The static HTML pages

First of all, what we are going to do is create a folder called “templates” in our project that is going to host all the static HTML pages. In that folder, you can find a footer and a header common for every website page, and they complete each other. You can already see that we are using some logic inside, such as the title <title>{head.title} | {global.appName}</title> will change with variables.

Apart from that, we have created the following:

  • The account creates the page with a simple form.
  • The account deletes a page, which is a confirmation page.
  • The account edit page has some sections where you can edit your account details, change your password and delete your account.
  • Checks create the page that contains a form to create a custom check.
  • A check edit page that lets us edit a previously open check
  • A checklist table containing an element that shows all the rows of checks we have
  • An index page that acts as the home page
  • A session-create and a session-delete page that displays logins and logouts.

A touchup of the configuration file will handle the extra information we want to add to the footer and header.

New helpers

He has then added four new helpers that help us render the different elements of the page, such as assets, templates and interpolation, to build dynamically the page requested by the user:

  1. getTemplate: This method retrieves the string content of a template file and performs string interpolation using the provided data object. It takes three parameters: templateName (string) — the name of the template file; data (object) — the data object for string interpolation; and callback — a callback function to handle the result.
  2. addUniversalTemplates: This method adds the universal header and footer templates to a given string. It uses the getTemplate method internally to retrieve the header and footer templates and performs string interpolation using the provided data object. It takes three parameters: str (string) — the string to which the header and footer templates are added; data (object) — the data object for string interpolation; and callback — a callback function to handle the result.
  3. Interpolate: This method takes a given string and a data object and performs string interpolation by replacing placeholders with corresponding values from the data object. It also adds the values of templateGlobals (defined in the config object) to the data object. It returns the interpolated string.
  4. getStaticAsset: This method retrieves the contents of a static (public) asset file. It takes two parameters: fileName (string) — the name of the asset file, and callback — a callback function to handle the result. It reads the file contents and returns them through the callback function.

Handlers update

Server.router has been updated in the server.js file to redirect the request of the different page to the correct handler. We designed a handler for each page that will return the right page. Now the object “handlers” contains several methods that serve as request handlers for different routes or endpoints. Each method follows a similar process:

  1. It checks if the request method is a GET. If not, it calls the callback function with a status code 405 (Method Not Allowed) and returns.
  2. If the request method is a GET, it prepares the necessary data for template interpolation based on the specific handler.
  3. It reads a corresponding template file and passes the prepared data to it.
  4. It adds the universal header and footer templates to the resulting HTML page.
  5. Finally, it calls the callback function with a 200 (OK) status code and returns the resulting HTML page.

In summary, each method handles a specific route or endpoint, prepares data, reads a template, adds headers and footers, and returns an HTML page. The templates and data vary depending on the purpose of each handler.

Revamping App.js

How do we let the server and client talk? We then updated the app object, adding the possibility to create AJAX requests that can query our node application. For those who do not know, an Ajax (Asynchronous JavaScript and XML) request is used in web development to send and receive data from a server asynchronously without requiring a full page reload. It allows for dynamic updates and interactions on a web page, where data can be retrieved or sent to the server in the background without disrupting the user experience.

In particular:

  1. App.client.request(headers, path, method, queryStringObject, payload, callback): This method is used to make an API call. It takes several parameters, including headers (object), path (string), method (string), queryStringObject (object), payload (object), and callback (function). It constructs an HTTP request based on the parameters and sends it to the specified path.
  2. App.bindLogoutButton(): This method binds the logout button element with an event listener. Clicking the button prevents the default action and calls the app.logUserOut() method to log the user out.
  3. App.logUserOut(redirectUser): This method logs the user out by sending a DELETE request to the “API/tokens” endpoint with the current session token. If the redirect is proper, it redirects the user to the “/session/deleted” page.
  4. App.bindForms(): This method binds all the forms on the page with event listeners for the submitted event. It prevents the forms from submitting, retrieves the form data, and calls the app.client.request() method to make an API call.
  5. App.formResponseProcessor(formId, requestPayload, responsePayload): This method is called when a form response is received. It processes the response based on the form ID and performs actions such as redirecting the user or displaying success/error messages.
  6. App.getSessionToken(): This method retrieves the session token from the local storage and sets it in the app.config.sessionToken property. It also updates the class of the body element based on the token’s presence.
  7. App.setLoggedInClass(add): This method adds or removes the “logged” class from the body element based on the add parameter.
  8. App.setSessionToken(token): This method sets the session token in the app.config.session token property and stores it in the local storage. It also updates the class of the body element based on the token’s presence.
  9. App.renewToken(callback): This method renews the session token by sending a PUT request to the “API/tokens” endpoint with the current token ID. If the renewal succeeds, it updates the token and calls the callback function false. Otherwise, it calls the callback function true.
  10. App.loadDataOnPage(): This method loads data on the current page based on the body class. It calls specific page-loading methods such as app.loadAccountEditPage() or app.loadChecksListPage().
  11. App.loadAccountEditPage(): This method loads the account edit page. It retrieves the user data based on the session token’s phone number and populates the form fields.
  12. App.loadChecksListPage(): This method loads the dashboard page. It retrieves the user data based on the session token’s phone number and performs actions specific to the dashboard page.

And that’s it!

Can you believe it? These are all the necessary steps to build a web app; now it’s ready to work! Now the application is prepared to render your static page, manage authentication, create checks, delete checks, and list your options.

--

--