Node Guide

Menu
Menu

Creating Web Pages with Node

The examples so far have focused on building an API to manage and supply data via endpoints. We can also use these technologies to dynamically build HTML pages based on values retrieved from our backend database.

Setting the Dynamic Web Pages

Clone this repo that provides a starting point to use the same database to build a series of web pages.

Ensure you run npm install to load the required modules and npm start dev to launch the application.

src/index.ts

This entry file has similar set up to the API example. There is also a routes file of:

src/routes/routes.ts

Here the homepage URL of localhost:3000/example will return a simple "Hello World". If we want a HTML page to be generated instead we need to add a view.

Working with Views

A view provides the user interface or presentation layer of the application. They represent the HTML templates or pages that are rendered and sent to the client's browser for display.

When using a view engine like EJS (Embedded JavaScript), you can dynamically generate HTML by embedding JavaScript code within your HTML templates. This allows you to insert dynamic data, conditionals, loops, and other logic into your views.

In an Express application, you typically define a directory to store your views, and this directory is often named "views" by convention. Inside the views directory, you create individual view files that correspond to different pages or components of your application.

To render a view and send it as a response to the client, you use the res.render() method provided by Express. This method takes the name of the view file (without the file extension) and an optional object containing data that you want to pass to the view. The view engine (e.g., EJS) processes the view file, executes any embedded JavaScript code, and generates the final HTML output.

Adding a View Template

To add a view template to our application add the following to index.ts.

SNIPPET: src/index.ts

The app.set("views", path.join(__dirname, "views")); and app.set("view engine", "ejs"); configures the application's view engine and specifies the directory where the view templates are located.

The "views" option specifies the directory path where the view templates are located.

__dirname is a global variable in Node.js that represents the current directory of the script file.

path.join(__dirname, "views") joins the current directory (__dirname) with the "views" directory, creating the absolute path to the views directory.

By setting the "views" option, Express knows where to look for the view templates when rendering them.

You will need to add the path module to use the __dirname. The path module is a built-in module in Node.js, so you don't need to install any additional packages via npm to use it. Therefore import path with:

SNIPPET: src/index.ts

The "view engine" option specifies the template engine to be used for rendering view templates.

In this case, the template engine is "ejs" (Embedded JavaScript), which is a popular template engine for generating dynamic HTML.

By setting the "view engine" option to "ejs", Express will automatically look for view templates with the ".ejs" file extension when rendering views.

Note: You need to install ejs via npm ie

npm install ejs

EJS View Files

Inside the src/views folder the repo already has a series of view files, but we'll start by building one from scratch.

Create a new file src/views/example.ejs. In Visual Studio Code this will be a blank document. Add the HTML skeleton by using EMMET shortcut of ! TAB.

In the body of the document use the EJS syntax to output/print a variable. The syntax used is:

So for example you could add:

src/views/example.ejs

When the EJS template is rendered, the value of the msg variable will be evaluated and inserted into the resulting HTML at the location of the <%= msg %> tag. This allows you to dynamically display data or variables within your HTML templates.

For example, if you have a variable name with the value "Joe Bloggs", using <%= name %> will output "Joe Bloggs" in the rendered HTML.

To use the view amend the GET route for localhost:3000/example/ with:

SNIPPET: src/routes/routes.ts

Here we use res.render("example", { msg: "Hello World!" }). This calls the render method on the res object to render an EJS template named "example". The second argument is an object that contains the data to be passed to the template. In this case, it includes a msg property with the value "Hello World!quot;.

It is good SEO practice that all titles in a web application are unique. Therefore, with templates a common technique is to send a value for the <title> of the HTML file.

Amend the view template with:

SNIPPET: src/views/example.ejs

Send a title variable via render in the router:

SNIPPET: src/router/router.ts

The dynamically set title value will now be used.

Note: You will get errors generated by the view if a value is referenced but not sent to it via render.

Using Javascript in the View

In the view the equal sign = in <%= %> is what distinguishes it as an output tag. If you don't need to output the value but want to execute JavaScript code within the template, you can use <% %> tags without the equal sign.

As such we could use some simple conditional logic in the View. First amend the route file to change the values sent:

SNIPPET: src/router/router.ts

Now the view receives title, newUser and msg, so we can build some simple conditional logic ie:

SNIPPET: src/views/example.ejs

In the template it is common to use Javascript loops, such as foreach to allow multiple lines of dynamic HTML to be generatedd when the view is sent an array via render. We'll look at that next.

Sending more complex data to a EJS View

In the controller file there is a getAllData method:

SNIPPET: src/controllers/controllers.ts

This will return all the film data to a calling route (as in the API version).

Create a route as:

SNIPPET: src/routes/routes.ts

There is a view file views/films.ejs that accepts the title for the view.

Test the page at localhost:3000/films

Amend the route to additionally send the data received from the controller. Add this to the render with:

SNIPPET: src/routes/routes.ts

The data is now attached to the films property of the object sent to the view.

Amend the view with:

SNIPPET: src/views/films.ejs

This will dump all the data providing the data has been successfully passed to the view.

Film Data Dumped in Browser

As the above is an array we could change the view to:

SNIPPET: src/views/films.ejs

Now the filmTitle of the first film in the array is displayed.

If we want all the films we should add a loop ie:

SNIPPET: src/views/films.ejs

Add some more HTML to the view with:

SNIPPET: src/views/films.ejs

Despite the additional HTML the pages don't appeared styled. We need to add a stylesheet. We look at that next.

Next: Static Web Content