EJS Partials

partials

Making our EJS more DRY and more easily maintanable.




Learning Objectives

  • EJS Partials

Prerequisites

  • JavaScript
  • Node
  • Express
  • EJS



Introduction

When building your apps so far during this unit, you may have noticed that if you wanted some pieces of consistent styling or wanted a certain element of your design visible across all your view, it required a lot of copy/pasting.

For example: for every single page, you had to copy/paste the entire HTML boilerplate. Or, if you want a navigation bar on every single page, you'd have to copy/paste the navigation bar html onto every single page.

You get the point, it's tedious and it's not DRY and if you make a change to a copy/pasted block of code on one EJS file, then you'd have to make the same changes in that block of code on all the EJS files you copied it to. So, it's not easily managable, either, once projects start getting large.

However! The EJS developers anticipated this problem, and implemented a nice little feature called partials.

Partials allow you to create reusable elements that can go on multiple pages and will allow you to streamline your EJS page creation and updates. How does that work? Let's find out!




Getting set up

In order to see how useful partials are and how exactly to use them, what we'll do is refactor code that doesn't use partials. In this case, we'll be going back to a slightly more advanced version of gitPub. Starter code is provided for you

Note: Because we're just focusing on EJS partials for this exercise, the provided app is not fully functioning with a proper mongo database or working create/delete routes. Hungry for more things to do in all your copious spare time? Try to make this app fully functional!




Getting the starter code ready

  • Fork and clone this git repo
  • run npm install so you install all then necessary packages for this project
  • code . inside the directory to open it up in vscode
  • nodemon to run the project
  • in your browser, go to http://localhost:3000/pub - you should see a landing page that looks like the image below



gitPub

If you look through the code / click through the gitPub pages, you'll notice there are several things that are or should be repeated throughout all pages of the app:

  • The css / everything inside the HTML <head>
  • The header
  • The footer

Now, consider the scenario where you want to make a change to the header. For example, let's say you want to add another link to the header navigation. Okay fine, all we have to do is add the link to the header on the index.ejs.

But, wait, now go to the show page -- uh-oh. The link we just added is no longer there. Okay, fine, we'll just add the link on show.ejs too. But if we do that, what do you think will happen on the new page? The link won't be there, so we'd have to change it there too!

Now pretend this is a large app with many different views that has the header on every single view - you'd have to make the change over and over again on every single view.

Now that one simple change that should have only taken a few seconds took a much longer time.

This is where partials come in super handy. They let you create reusable EJS that you only have to edit in one place and it will update across all your pages where the partial is included.

Let's create our first partial to really see how this works.




Creating the <head> partial

In terminal make sure you're still in the gitpub directory and run:

  • mkdir views/partials
  • touch views/partials/head.ejs

Right now, only our index view has styling. That's not a good look, so let's cut that code out of the index's head and paste it into our head.ejs file

<meta charset="utf-8" />
<title>gitPub</title>
<!-- ============= FONTS ============= -->
<link
	href="https://fonts.googleapis.com/css?family=Inconsolata:400,700|Montserrat:300,400,700&display=swap"
	rel="stylesheet"
/>
<!-- ============= STYLES ============= -->
<link rel="stylesheet" href="/css/styles.css" />

Now if we save and refresh our index, the CSS is gone! Oh no! But, no worries, we saved all that code in our head.ejs partial, and now all we need to do to utilize that partial is include it back into the head of our index.ejs using the following syntax:

<% include ./partials/head.ejs %>

Make sure you've saved all your files and refresh your index -- voila! Our CSS is back! We've successfully included our partial.

Now, all we have to do is include the partial on all the other pages as well. Copy/paste the include into:

  • new.ejs
  • showDrinks.ejs
  • showFood.ejs

If you check each view in your browser, they should all now be styled!




Creating the header partial

Alright, now let's clean up our files a bit so there's less repetition. We saw earlier that every single page has the <header>, so that's definitely a good candidate for a partial.

Let's do the same thing we just did:

  • Create a header.ejs file in our partials folder
  • Cut out the header code from all the files and paste it into the header.ejs file
<header>
	<h1>gitPub.io</h1>
	<ul>
		<li><a href="/pub">master branch</a></li>
		<li><a href="/new">git add -an item</a></li>
	</ul>
</header>
  • Include the header partial in: index.ejs, new.ejs, showDrinks.ejs, showFood.ejs
<% include ./partials/header.ejs %>



Our ejs files are looking so much cleaner already! But there's one more repetitive thing we can get rid of, so let's create a partial for the footer!

  • Create a footer.ejs file in our partials folder
  • Cut out the footer code from all the files and paste it into the footer.ejs file
<footer>
	<span>℗ 2019</span>
	<span>FORKED FRMO STAMFORD.</span>
</footer>
  • Include the footer partial in: index.ejs, new.ejs, showDrinks.ejs, showFood.ejs
<% include ./partials/footer.ejs %>

Sweet, our code looks so DRY! And -- oh, wait there's a typo in our footer. Let's fix that up.




In footer.ejs

  • Fix the typo: FRMO should be FROM

Now check all our pages -- nice, it's fixed for all of them and we only had to change it in that one file.




Other extra things to note

Using variables in partials

Just like any other .ejs file, you can use variables inside your partials. You just have to make sure that wherever you use that partial, that variable is actually defined.

For example, let's say we want our tab titles to be variable depending on the page you're on. Our <title> is in our head.ejs partial, so let's go there!

In head.ejs

Let's create a variable called tabTitle that will determine what the title is. So, let's go ahead and put that in.

<title>gitPub | <%=tabTitle%> </title>

If you try to view any of the pages now, it throws us an error saying tabTitle is not defined - let's define it!




In server.js

We'll start in the index route first. In our res.render object, let's pass it another variable for tabTitle now. For the index, let's just give it a title of Home:

res.render('index.ejs', {
  drinks: drinks,
  tabTitle: 'Master Branch'
}

Now if we refresh our index in the browser, it works! Great! But, if we try to go to any other page, it gives us the not defined error again. But we just defined it, didn't we?

We did - but only in the index route! Variables for partials are passed down via their parent.

So, because we defined tabTitle in our index route, it passed it to index.ejs. Because index.ejs includes the head.ejs partial, it passed the variable down into the partial as well.

However, consider our show route. We did not define the tabTitle variable there, so it wasn't passed down to show.ejs, and thus the head.ejs partial included there does not have access to the tabTitle variable, hence the error.

To fix it then, let's define the tabTitle on all our other views!




In the show route

res.render('show.ejs', {
  drink: drinks[req.params.id],
  tabTitle: 'fooBar()'
}



In the new route

res.render('new.ejs', {
  tabTitle: 'add -A'
}

If you check all your views now, they should all work and have different titles depending on the page! 🎉