Building my Portfolio Page using the Handlebars JavaScript Library
Recently, I finished and deployed my personal portfolio. I discovered the handlebars library when reviewing JavaScript on Codecademy. Handlebars is a templating engine which allows for the generation of reuseable HTML. Handlebars allows for a clear separation between JavaScript and HTML. I found that this library was particularly useful in displaying the blog posts and projects on my portfolio. In this blog post, I will go through an overview of how to implement the Handlebars library in a project. I will also highlight some of the features that I found useful and how I implemented Handlebars in my personal portfolio.
Implementation
The first step is to add the handlebars library to your project. This can be done in two ways. The handlebars library can be downloaded and put into the project directory where it is referenced. The handlebars library can also be imported from a content delivery network (CDN) which is what I used for my project.
In the HTML file, the handlebars library can be referenced using a script tag as follows:
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.js"></script>
The handlebars script needs to be created. This is where the template will be written that will be repeatedly be used. The handlebars script will be given an id for referencing later.
<script id=“ice-cream” type=“text/x-handlebars-template”></script>
In the JavaScript file, the HTML in the handlebars script is grabbed using getElementbyId. This will allow us to pass the template to a function.
const source = document.getElementById('ice-cream').innerHTML
The template is then passed to the compile function in the Handlebars library to get the templating function.
const template = Handlebars.compile(source)
A context object is created in the JavaScript file. The context file contains information that will be used by handlebars expressions in the template. The context object is passed into the templating function to get the complied HTML that will be rendered to the page.
const context = {
flavor: 'vanilla'
}const compliedHTML = template(context)
The final step is rendering the HTML to the page. The HTML element where the information is to be rendered is selected and the inner HTML of this element is set to the rendered HTML.
const iceCreamText = document.getElementById('scream')
iceCreamText.innerHTML = compliedHTML
Handlebars expressions
The power of using this library is the reusability and consistency of the template in the handlebar script. The template inside the script uses Handlebars expressions which are denoted by double braces. The content in the Handlebars expressions are replaced by values determined by the context object.
<script id="ice-cream" type="text/x-handlebars-template">{{flavor}} is the best!</script>
The Handlebars library also has conditional rendering using if-else expressions:
{{#if argument}}
// Code to include if the provided argument is truthy
{{else}}
// Code to include if the provided argument is falsy
{{/if}}
The each expression allows you to iterate through an array in the template script. The this expression is replaced by the elements of the array. The this expression can also be used to access properties of the object
{{#each someArray}}
<p>{{this}} is the current element!</p>
{{/each}}
The handlebars expressions can be combined to allow of interesting control of what gets displayed by the template. This was used on my personal portfolio site.
Using the Handlebars library on my portfolio
In this section, I will discuss the use of the Handlebars library on my projects page. The following is the handlebars template that I created in the HTML file:
<script id="projects-template" type="text/x-handlebars-template"> {{#each projects}}
<div class="project">
<img src={{this.project_photo}} alt="">
<div class="project-info">
<h1>{{this.title}}</h1>
<p>{{this.description}}</p>
<h2>Technology Stack:</h2>
<p>Technology Stack: {{this.tech}}</p>
{{#if this.private}}
{{else}}
{{#if this.deployed}}
<div id="project-links">
<a href={{this.github_url}} target=_blank><i class="fab fa-github"></i></a>
<a href={{this.deployed_url}} target=_blank><i class="fas fa-globe"></i></a>
<a href={{this.demo_url}} target=_blank><i class="fab fa-youtube"></i></a>
</div>
{{else}}
<div id="project-links">
<a href={{this.github_url}} target=_blank><i class="fab fa-github"></i></a>
<a href={{this.demo_url}} target=_blank><i class="fab fa-youtube"></i></a>
</div>
{{/if}}
{{/if}}
</div>
</div>
{{/each}}
</script>
The context object provided is as follows:
const context = {
projects: [
{
title: "Maripilot Website",
description: "Full stack web application for the Maripilot Company. The user interface allows for users to use a business planning tool and a messaging board to connect with other users. The user interface is built in React and the backend is written in Ruby on Rails. The user information and messages are stored in a PostgreSQL relational database. JWT authentication is used for user login. An administration login is created for the moderation and management of the messaging board.",
tech: "React, Ruby on Rails",
project_photo: "./photos/Maripilot_Logo.png",
private: true
},
{
title: "Rave Mom",
description: "Personalized browser based game built in the Phaser 3 JavaScript library. Rave Mom is a one player survival game with a scoring system that is a variation on the classic Bomberman game. The back end is written in Ruby on Rails. The user's information and scores are stored in a PostgreSQL relational database. JWT authentication is used for the user login. The game is deployed on Google Firebase and Heroku.",
tech: "Phaser 3, JavaScript, Ruby on Rails, Heroku, Google Firebase",
project_photo: "./photos/Rave_Mom_Screenshot.png",
demo_url: "https://www.youtube.com/watch?v=3kBx_M08VB8&t=17s",
github_url: "https://github.com/evantk91/rave-mom-app",
deployed: true,
deployed_url: "https://rave-mom.firebaseapp.com/",
private: false
},
{
title: "Three Card Poker",
description: "Full stack web application that simulates the three card poker casino game. The single page front end user interface is written in vanilla JavaScript and the back end is written in Ruby on Rails. The user's information and scores are stored in a PostgreSQL relational database. JWT authentication is used for user login. The application is deployed on Heroku and Google Firebase.",
tech: "JavaScript, Ruby on Rails, Heroku, Google Firebase",
project_photo: "./photos/Three_Card_Poker_Screenshot.jpg",
demo_url: "https://www.youtube.com/watch?v=T3Eti6dAlXk&t=6s",
github_url: "https://github.com/evantk91/three-card-poker-frontend",
deployed: false,
private: false
}
]
}
The context object above allows for the adding of new projects in a fairly straight forward way. The conditional rendering allows for the display of projects that are private where access to the git repository is not shown and projects that are not deployed for current use. I used a similar template for the display of my blog posts on the home page.
Conclusion
Handlebars was a useful library to learn. I found that the library was very applicable to setting up my personal portfolio where changes to the content of the page were reasonably frequent. I found that using this library was straight forward for use on any vanilla JavaScript website and a good introduction to more complex libraries such as React.js.