DEV Community

loading...

Using Includes/Partials In PugJS

nkratzmeyer profile image Nathan Kratzmeyer ・4 min read

This post is the fourth in a short series on using the PugJS view engine with NodeJS and ExpressJS. In the last part, we covered using PugJS to display dynamic data. In this post, we'll cover the concept of using includes (as named in the PugJS documentation). I prefer to call them "partials" and will do so in this article. Let's get started!

Starting Code

Below is our starting code (slightly modified since the last post).

//index.js
const express = require('express');

const userNames = ['Sean', 'George', 'Roger', 'Timothy', 'Pierce', 'Daniel']
const bestMovie = 'Casino Royale';
const licensedToKill = true;

const app = express();

app.set('view engine', 'pug');

app.get('/', (req, res) => {
    res.render('index', {
        userNames,
        bestMovie,
        licensedToKill,
        title : "Home Page"
    });
});

app.get('/about', (req, res) => {
    res.render('about', {
        userNames,
        title : 'About'
    });
});

app.listen(3000, () => {
    console.log('Server listening on 3000');
});
//- main-layout.pug
<!DOCTYPE html>
html(lang="en")
    head
        title #{ title }
    body
        header
            nav
                ul
                    li 
                        a(href="/") Home
                    li
                        a(href="/about") About
        h1 This h1 is from the layout.
        hr
        block content
        section
            h2 This h2 is also from the layout
            for user in userNames
                li= user
        block more_content
//- Index.pug
extends layouts/main-layout.pug
block content
    if licensedToKill
        p Bond is licensed to kill!
    else
        p Bond is NOT licensed to kill!
block more_content
    p The best movie is #{ bestMovie }
    p= bestMovie
//- about.pug
extends layouts/main-layout.pug
block content
    p This content is from about.pug!
    p About my cool site!

And here is our folder layout

project_folder
├── index.js
├── node_modules
├── package.json
├── package-lock.json
└── views
    ├── about.pug
    ├── index.pug
    ├── layouts
    │   └── main-layout.pug

About Partials (Includes)

The concept behind includes is very simple. It gives us a mechanism to pull in the contents of one file into another. To do this, we use the include keyword followed by the path to a partial file. It is somewhat similar to the the "layout" concept discussed in the previous posts in this series. I like to think of the template system as a good way to create a general layout for your site whereas partials provide a good way to create modular components that can be reused. Let's see how we can integrate partials into our existing code.

Using a Partial For the Header

The header element in our main-layout file seems like a good candidate for a partial. In a real website, the header and nav elements could get a little complex and it would be nice to separate the header into a different file for easier readability and maintenance. To start, create a new folder under views called partials. Then create a new file in the partials folder called header.pug. Now cut the header element from main-layout and paste into header.pug. We'll also add an h1 with some text. It should look like this:

//- header.pug
header
    nav
        ul
            li 
                a(href="/") Home
            li
                a(href="/about") About
    h1 This page title is coming from header.pug -- #{ title }

In main-layout.pug include the header by adding this line where the header previously was. Be sure to indent properly. It should be indented one tab further than our body element:

    include ../partials/header

Now if you view your page, you should see that we have the same end result. If you view the page source in the browser, you should see that we have well-formed HTML. If you don't have well formed html, there is an error in your pug syntax.
In our contrived example, there's not a lot of advantage to doing it this way. However, as previously noted, this could be pretty helpful in a more complex website. Let's do something slightly more useful.

Create a User Card

Now we'll create a reusable component for displaying a user. Create a new file in partials called user.pug with this content:

div.card
    p= user

When this is translated into html, we will get a div with a class of card. In main-layout.pug, modify the users list to:

for user in userNames
    include ../partials/user.pug

Now if we wanted to display a user anywhere in our site, we can just include our user.pug being sure that it has access to a user object.
As further practice, you could create a partial for a footer or another nav element. IMPORTANT NOTE: In these examples, I've only used partials in the main-layout file. However, this is not a requirement. We can use the include keyword in any pug file.

Avoid This!

You might think that we could change the first line of our index.pug to this:

include partials/main-layout.pug

However, this won't work! The html and body tags will be closed off too early and our html will be all jacked up!

Conclusion

In this post I've gone over using includes/partials in PugJS. We've seen how to split pieces of our views into separate files to aid reuse and readability. Hopefully this post was informative and, as always, corrections/comments/critiques are welcome!

Discussion (11)

Collapse
alexsc6955 profile image
Noel A Rodriguez

Hello. This is well explained, and I have a question.

Let's say I want to dynamically change a tag when I include a pug file. Is it possible? For example, I have this form which I want to use in two different pages in my project but at home, it is in a modal. Its title is inside .modal-header with the tag .modal-title, The form fields are inside .modal-body and the submit button, inside .modal-footer.

Now, I need to load the same form in another page but without the modal tags. How can I do that?

Collapse
nkratzmeyer profile image
Nathan Kratzmeyer Author

I didn't cover this in my posts but I think a mixin is what you'd want to use in this case. Pug mixins are documented here. If you have troubles figuring out how to make that work, I'd be glad to write up another article showing a scenario similar to yours.

Another alternative would be to just use client-side JavaScript to add/remove CSS classes from your elements.

Hope that helps!

Collapse
alexsc6955 profile image
Noel A Rodriguez

Did it.

I created a mixin for the modals (Actually I'm using two with different forms, I pass the params I need and it includes the forms. Even though it would be great if you write another article about it. Thank you.

Thread Thread
nkratzmeyer profile image
Nathan Kratzmeyer Author

Let me see what I can work up!

Thread Thread
nkratzmeyer profile image
Nathan Kratzmeyer Author

Done! Its quick & dirty but hopefully you'll find it useful.

Thread Thread
alexsc6955 profile image
Noel A Rodriguez

Thank you. I'll share with you my solution.

Collapse
alexsc6955 profile image
Noel A Rodriguez

Thank you so much. I'm going to try it. I'll let you know.

Collapse
alexsc6955 profile image
Thread Thread
nkratzmeyer profile image
Nathan Kratzmeyer Author

Did you check out my last post?
dev.to/nkratzmeyer/using-mixins-wi...
You can use the implicit attributes of a mixin to set attributes (including classes, id's, etc) on elements inside the mixin.

Thread Thread
alexsc6955 profile image
Noel A Rodriguez

Yeah! I checked it but when I wrote this I had not read your post. I will implement it following your post. Thank you.

Collapse
corsica2a profile image
Corsica2A

Hello,

I'm a student and I'm looking for somebody to help me about 2 problems with pugjs.
Please, could you help me ? I have 2 problems... and I have to find a solution before saturday...
First, I want to display a picture for specific days. Moreover, I'll like creating a calendar.
It will be very kind if you could help me.

Best regards

Forem Open with the Forem app