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.
This entry file has similar set up to the API example. There is also a routes file of:
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
.
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:
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
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:
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:
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:
Send a title variable via render
in the router:
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:
Now the view receives title
, newUser
and msg
, so we can build some simple conditional logic ie:
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:
This will return all the film data to a calling route (as in the API version).
Create a route as:
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:
The data is now attached to the films
property of the object sent to the view.
Amend the view with:
This will dump all the data providing the data has been successfully passed to the view.
As the above is an array we could change the view to:
Now the filmTitle
of the first film in the array is displayed.
If we want all the films we should add a loop ie:
Add some more HTML to the view with:
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