Loading...

Express - Views and templating with Pug

Intro

Express is a framework for creating application that runs on the server. Express is an unopinionated minimal framework which makes it very easy to start being extremly productive. In today's lesson we will learn about creating views with express. By views we mean make our server return an HTML page to the user. We will learn how to combine Express with a templating language specifically Pug and learn basic functionality using Pug.

Bootstrap express

Lets start with openning a new directory for our project called express-views In that directory we will init npm and install express.

        
            > mkdir express-views
            > cd express-views
            > npm init --yes
            > npm install express --save
        
    

In the root directory of our project create a file called: app.js We will start by creating a simple server that sends hello world for every route

        
            const express = require('express');

            const app = express();
            app.get('*', function(req, res) {
                res.send('hello world');
            });
            app.listen(3001, function() {
                console.log('server is now listening on port 3001');
            });
        
    
Express options

When creating an express app using:

        
            const app = express();
        
    

Express expose to us application settings properties with default values that we can modify. The full list of properties is available here To change the default values of the properties we can use app.set(property, value) Regarding the express Views we have a few intresting options:

  • views - this option tells express where the directory we are storing the templates. This option can also hold an array of directories in case we have more than one directory for the views. Bare in mine that you will have to supply the full absolute pate
  • view engine - this option tells express what templating engine we are using. For this tutorial we will use Pug

After creating the express app add the following lines:

        
            const path = require('path');
            app.set('views', path.resolve(__dirname, 'views'));
            app.set('view engine', 'pug')
        
    

In this code we are grabbing the path package. We are using the path package to create the absolute url for the views option. the url of the view will be __dirname, which is the absolute path that app.js resides in, plus views. We set the templating engine for the express views as Pug. Create a directory called views in the root directory of the project. We will also need to install pug using npm:

        
            > mkdir views
            > npm install pug --save
        
    
Our first Pug template

With pug installed and the express options for using pug are set, we can now call res.render on the response object. the first argument of this function is the relative path to the template, relative to our views directory. Our templates extension will be pug and the path for the render. does not need to include the extension. The second argument for the render method is the variables we are passing to our template. The result of the render method is an HTML response of the rendered template. Lets try to create a pug template and go over the common features you will most likely use the most when creating templates. In the views folder, create a file called todo.pug. Lets create a page which displays list of todo item. Edit the todo.pug file with the following code

        
            doctype html
            html
                head
                    title Todo Application
                body
                    h1(class="greeting") Todo
                    p List of todo items
                    ul
                        li Buy Tofu
                        li Buy Soya Milk
                        li Buy Vegetables
        
    

Also in the file app.js we will tell express to render our template. Change the following code in app.js from this:

        
            app.get('*', function(req, res) {
                res.send('hello world');
            });
        
    

to this:

        
            app.get('*', function(req, res) {
                res.render('todo');
            });
        
    

Kind of weird writing our HTML like this, so it takes a bit of time to get used to but lets cover the main features of pug and try to practice them in this tutorial. First you will notice that indentation matters, and pug uses this to know what tag resides in what parent. If you want to create a tag you should simply write the tag name. So we start an HTML document with doctype tag and specify that it's HTML doctype. We then create an html tag and inside it we place a head tag. in the head we place a child tag called title. notice that the title tag has a text between the openning and closing title tag. To specify text in a tag we simply write the text after placing a space after the tag name. If we want to add attribute to a tag, you can see how we dealt with the h1 tag. We simply call the tag like a function and place the attribute inside the brackets like we did with the class attribute. We then place a ul tag with hardcoded todo list of items. After you get used to the weird syntax it becomes even clearer then HTML. You don't have to worry about openning closing tags, and pug will know if a tag is self closing. Lets try and pass data from express to the template.

pug - passing variables and loops

Lets make the hard coded list in our pug template to a more dynamic list. Specifically we will add an array in app.js of todo items and pass that array to our template. In our app.js change the following:

        
            app.get('*', function(req, res) {
                res.render('todo');
            });
        
    

to this:

        
            const todoItems = [
                'Buy Tofu',
                'Buy Soya Milk',
                'Buy Vegetables',
                'Finish Article'
            ];
            app.get('*', function(req, res) {
                res.render('todo', {items: todoItems});
            });
        
    

We define an array in memory that holds the todo items. We then pass a second argument to the render method with an object, with keys as variable names that will be available in our template, and values as the variable content. So we define a variable called items that will be available in the template and populated that variable with the array we defined. Now in the template edit to look like this:

        
            doctype html
            html
                head
                    title Todo Application
                body
                    h1(class="greeting") Todo
                    p List of todo items
                    ul
                        - for(let item of items)
                            li= item
        
    

We made the changes in the ul section. The first line is plain old javascript, a nice feature in pug templates that i failed to notice in other templating engine is the ability to straight up place javascript code. we are using the sign - this tells pug we are inserting js code. We placed a loop that iterates of the items - notice how we can now use items globally since we injected it in the express res.render method. Notice also the importance of indentation, since we placed an indent after the for, then the scope of the li is inside our loop (no need for curly braces). So it's really easy place js code in our template, lets see how we can utilize this feature for template conditions.

Pug - conditions in template

lets pass a variable from the express to the template, the variable will determine if the user requesting the page is an admin user. If the user is admin user we will write it in the page. Modify the app.js render section to this:

        
            app.get('*', function(req, res) {
                res.render('todo', {items: todoItems, isAdmin: true});
            });
        
    

Now modify our template to this:

        
            doctype html
            html
                head
                    title Todo Application
                body
                    h1(class="greeting") Todo
                    p List of todo items
                    ul
                        - for(let item of items)
                            li= item
                    - if (isAdmin)
                        h3 hello admin user
                    - else
                        h3 hello guest user
        
    

Notice what we added at the bottom. Again we are inserting js code and now we are inserting an if statement, if the isAdmin is set to true then we display an h3 with a greeting to the admin, otherwise we are greeting the guest user. Lets say we have a footer in our app that will repeat in many pages. Lets see how we can add a repeating snippet in our pug template.

Include partial templates

Create a file in the views directory called footer.pug with the following code

        
            footer
                h3 this is the footer
                img(src="/images/stam.png")
                p= userName
        
    

we are placing a footer tag. Under the footer tag we are placing an img. Notice the path for the image cause we will need to make express serve this image. We are also printing a variable named userName inside a paragraph tag. Now to include this footer in our todo template. Modify the todo.pug and add the following to the bottom of the file.

        
            include footer
        
    

Notice that the path to the included pug templates is relative to the current template. Also if the extension of the template is pug it can be omitted. The footer is using a variable called userName so we need to pass it to the main todo template. In the app.js modify the function that renders the template:

        
            app.get('*', function(req, res) {
                res.render('todo', {items: todoItems, isAdmin: true, userName: 'Yariv'});
            });
        
    

We are including an image in the footer, so we have to tell express that under the route /assets we want to serve static files. We can use express static middleware to do that. We can tell the middleware to be used under the route /assets and to point the middleware to our asset directory. Create a directory in the root directory of the project called: assets In that directory create another directory to store the images, call this directory images. We are including an image called stam.png so copy a png image to that directory and rename the file to stam.png or change the filename in the template. Now lets add the express static middleware. In the file app.js after creating the express app, add the following line to load the express static middleware.

        
                app.use(express.static(path.resolve(__dirname, 'assets')));
        
    

We are telling express that when he sees a path starting with images he should grab it from the assets directory. Test your app and you should see the footer is rendering with an image and also the user name we passed.

Pug - template inheritance

Another really usefull feature in pug is the template inheritance. There is a use case for this feature in almost every application you will build. Lets examine an example of a common use case. When creating a web application, it's common to have a certain layout of a page that will repeat in some if not all our pages of the app. For example lets say we have an app with a homepage, an about page and a dashboard page. Each of those page have a certain common layout with a header and a footer that is repeating in all of our pages. One way to deal with the is to add an include for header and footer for each one, but still we will have to repeat those includes everywhere. Another better way is to define a layout. Define block in the layout of content that can be included from template that inherit from the layout. We can also place a default values in the block content. Create a file called layout.pug in the views directory. This will be the parent layout and every page we have will inherit from this parent. Edit that file to this:

        
            doctype html
            html
                head
                    title Todo Application
                body
                    block content
                    block footer
                        include footer
        
    

Notice that using the layout page we can now avoid including all the boiler plate html and head tags which will probably also be identical to other pages. Now modify the todo.pug to inherit from this template.

        
            extends layout

            block content
                h1(class="greeting") Todo
                    p List of todo items
                    ul
                        - for(let item of items)
                            li= item
                    - if (isAdmin)
                        h3 hello admin user
                    - else
                        h3 hello guest user
            
            block append footer
                h5 this is the todo page
        
    

look how clean and short our page will become. Each page is just modifying the block relavent to him and not creating every time the entire html from scratch. on the top of the file (it has to be the top) we are using the extends keyword to tell pug the parent from which we are inheriting (relative path to the current template file). We are then telling pug using the block keyword, which block we are overriding. We can also append to the default block like we are doing in the footer.

Summary

This tutorial covered express views. We saw how we can combine a templating engine with our express app and we then drill down on creating templates using pug. We covered the main most used features of pug and we saw how to place js code in our template, inject variables, loop and condition, include partials and template inheritance. Up to you now to practice express views and it will become easier as you go along.