Thursday, January 2, 2020

How To Create Better Angular Templates With Pug

As a developer, I appreciate how Angular apps are structured and the many options the Angular CLI makes available to configure them. Components provide an amazing means to structure views, facilitate code reusability, interpolation, data binding, and other business logic for views.
Angular CLI supports multiple built-in CSS preprocessor options for component styling like Sass/SCSS, LESS, and Stylus. However, when it comes to templates, only two options are available: HTML and SVG. This is in spite of many more efficient options such as Pug, Slim, HAML among others being in existence.
In this article, I’ll cover how you — as an Angular developer — can use Pug to write better templates more efficiently. You’ll learn how to install Pug in your Angular apps and transition existing apps that use HTML to use Pug.
Pug (formerly known as Jade) is a template engine. This means it’s a tool that generates documents from templates that integrate some specified data. In this case, Pug is used to write templates that are compiled into functions that take in data and render HTML documents.
In addition to providing a more streamlined way to write templates, it offers a number of valuable features that go beyond just template writing like mixins that facilitate code reusability, enable embedding of JavaScript code, provide iterators, conditionals, and so on.
Although HTML is universally used by many and works adequately in templates, it is not DRY and can get pretty difficult to read, write, and maintain especially with larger component templates. That’s where Pug comes in. With Pug, your templates become simpler to write and read and you can extend the functionality of your template as an added bonus. In the rest of this article, I’ll walk you through how to use Pug in your Angular component templates.

Why You Should Use Pug

HTML is fundamentally repetitive. For most elements you have to have an opening and closing tag which is not DRY. Not only do you have to write more with HTML, but you also have to read more. With Pug, there are no opening and closing angle brackets and no closing tags. You are therefore writing and reading a lot less code.
For example, here’s an HTML table:
<table>
   <thead>
       <tr>
           <th>Country</th>
           <th>Capital</th>
           <th>Population</th>
           <th>Currency</th>
       </tr>
   </thead>
   <tbody>
       <tr>
           <td>Canada</td>
           <td>Ottawa</td>
           <td>37.59 million</td>
           <td>Canadian Dollar</td>
       </tr>
       <tr>
           <td>South Africa</td>
           <td>Cape Town, Pretoria, Bloemfontein</td>
           <td>57.78 million</td>
           <td>South African Rand</td>
       </tr>
       <tr>
           <td>United Kingdom</td>
           <td>London</td>
           <td>66.65 million</td>
           <td>Pound Sterling</td>
       </tr>
   </tbody>
</table>
This is how that same table looks like in Pug:
table
 thead
   tr
     th Country
     th Capital(s)
     th Population
     th Currency
 tbody
   tr
     td Canada
     td Ottawa
     td 37.59 million
     td Canadian Dollar
   tr
     td South Africa
     td Cape Town, Pretoria, Bloemfontein
     td 57.78 million
     td South African Rand
   tr
     td United Kingdom
     td London
     td 66.65 million
     td Pound Sterling
Comparing the two versions of the table, Pug looks a lot cleaner than HTML and has better code readability. Although negligible in this small example, you write seven fewer lines in the Pug table than in the HTML table. As you create more templates over time for a project, you end up cumulatively writing less code with Pug.
Beyond the functionality provided by the Angular template language, Pug extends what you can achieve in your templates. With features (such as mixins, text and attribute interpolation, conditionals, iterators, and so on), you can use Pug to solve problems more simply in contrast to writing whole separate components or import dependencies and set up directives to fulfill a requirement.

Some Features Of Pug

Pug offers a wide range of features but what features you can use depends on how you integrate Pug into your project. Here are a few features you might find useful.
  1. Adding external Pug files to a template using include.

    Let’s say, for example, that you’d like to have a more succinct template but do not feel the need to create additional components. You can take out sections from a template and put them in partial templates then include them back into the original template.

    For example, in this home page component, the ‘About’ and ‘Services’ section are in external files and are included in the home page component.
    //- home.component.pug
    h1 Leone and Sons
    h2 Photography Studio
    
    include partials/about.partial.pug
    include partials/services.partial.pug
//- about.partial.pug
h2 About our business
p Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
//- services.partial.pug
h2 Services we offer
P Our services include: 
ul  
    li Headshots
    li Corporate Event Photography
 
Reusing code blocks using mixins.

For example, let’s say you wanted to reuse a code block to create some buttons. You’d reuse that block of code using a mixin.
mixin menu-button(text, action)
    button.btn.btn-sm.m-1((click)=action)&attributes(attributes)= text

+menu-button('Save', 'saveItem()')(class="btn-outline-success")
+menu-button('Update', 'updateItem()')(class="btn-outline-primary")
+menu-button('Delete', 'deleteIte
()')(class="btn-outline-danger")
 


 
Conditionals make it easy to display code blocks and comments based on whether a condition is met or not.
- var day = (new Date()).getDay()

if day == 0
   p We’re closed on Sundays
else if  day == 6
   p We’re open from 9AM to 1PM
else
   p We’re open from 9AM to 5PM
 
Iterators such as each and while provide iteration functionality.
ul
 each item in ['Eggs', 'Milk', 'Cheese']
   li= item

ul
 while n < 5
   li= n++ + ' bottles of milk on the wall'
 

  1. Inline JavaScript can be written in Pug templates as demonstrated in the examples above.
  2. Interpolation is possible and extends to tags and attributes.
    - var name = 'Charles'
    p Hi! I’m #{name}.
    
    p I’m a #[strong web developer].
    
    a(href='https://about.me/${name}') Get to Know Me
     
    Filters enable the use of other languages in Pug templates.
    
    For example, you can use Markdown in your Pug templates after installing a JSTransformer Markdown module.
    :markdown-it
       # Charles the Web Developer
       ![Image of Charles](https://charles.com/profile.png)
    
       ## About
       Charles has been a web developer for 20 years at **Charles and Co Consulting.** 
     
     
    These are just a few features offered by Pug. You can find a more expansive list of features in Pug’s documentation