Angular Templates with Pug

Write cleaner, more maintainable Angular component templates with Pug's indentation-based syntax and powerful features like mixins and includes.

What is Pug and Why Use It with Angular

Pug (formerly known as Jade) is a high-performance template engine that compiles to HTML, offering a simplified syntax that uses indentation instead of closing tags. Originally called Jade, it was renamed to avoid trademark conflicts, but the philosophy remains the same: write less code, reduce repetition, and maintain clarity.

The HTML Verbosity Problem

Traditional HTML templates require explicit opening and closing tags for every element, which becomes problematic as templates grow in complexity. A typical Angular component with multiple nested elements, structural directives, and repeated UI patterns can easily become unwieldy. Tables, forms with multiple input fields, and complex card layouts all suffer from HTML's verbose tag structure.

Consider a data table displaying country information. In HTML, each cell requires opening and closing tags, creating dozens of lines of repetitive code. Pug condenses this significantly while maintaining clarity about the structure.

Pug addresses several pain points that Angular developers face daily:

  • Reduced boilerplate - No closing tags means less repetitive code
  • Clearer structure - Indentation shows nesting visually
  • Reusable patterns - Mixins enable template-level componentization
  • Smaller files - Faster navigation and smaller git diffs

Pug's template engine approach eliminates matching opening and closing tags, reducing syntax errors and making template structure visually apparent. The cleaner syntax also means faster navigation in code editors and reduced git diffs when making changes.

For teams focused on web development best practices, adopting Pug can significantly improve template maintainability across large Angular codebases.

HTML Template (Verbose)
1<table>2 <thead>3 <tr>4 <th>Country</th>5 <th>Capital</th>6 <th>Population</th>7 </tr>8 </thead>9 <tbody>10 <tr>11 <td>Canada</td>12 <td>Ottawa</td>13 <td>37.59 million</td>14 </tr>15 <tr>16 <td>United Kingdom</td>17 <td>London</td>18 <td>66.65 million</td>19 </tr>20 </tbody>21</table>
Pug Template (Clean)
1table2 thead3 tr4 th Country5 th Capital6 th Population7 tbody8 tr9 td Canada10 td Ottawa11 td 37.59 million12 tr13 td United Kingdom14 td London15 td 66.65 million

Setting Up Pug in Your Angular Project

Integrating Pug with Angular requires configuration since Angular CLI doesn't support it out of the box. The recommended approach uses ng-cli-pug-loader, a community-maintained loader that seamlessly integrates Pug compilation into the Angular build process.

Installation

ng add ng-cli-pug-loader

This command installs the package and configures your angular.json to process .pug files. For existing projects or specific version requirements:

npm install --save-dev ng-cli-pug-loader

The loader intercepts .pug file imports during the build process and compiles them to HTML before Angular processes them. The configuration is straightforward and works with both new and existing Angular projects.

Alternative: ngx-pug-loader

For projects requiring more customization, ngx-pug-loader offers an alternative approach using Angular's custom webpack configuration or Angular builders. This method provides finer control over the compilation process and may be preferable for complex build setups or projects using Angular versions that have compatibility issues with ng-cli-pug-loader.

Community solutions for Angular CLI integration provide detailed guidance on both approaches, helping you choose the right method for your specific project requirements.

Streamlining your web development workflow with optimized build tools like Pug loaders can significantly improve team productivity.

Key Pug Features for Angular

Powerful template capabilities that enhance Angular development

Mixins

Define reusable template snippets that can be used across multiple components, similar to Angular components but at the template level.

Includes

Split large templates into smaller, manageable files for better organization and maintainability.

Clean Syntax

Indentation-based syntax eliminates closing tags and reduces overall template code volume.

Attribute Interpolation

Clean syntax for complex attribute structures with Angular bindings and directives.

Angular Template Syntax in Pug

One of the most critical aspects of using Pug with Angular is correctly translating Angular's template syntax to work within Pug's compilation context.

Property and Event Bindings

Angular's property bindings use square brackets [] and event bindings use parentheses (). In Pug, these characters must be quoted or separated with commas to prevent conflicts with Pug's syntax:

// Property binding - use quotes
img([src]='itemImageUrl', [style.border]='imageBorder')

// Event binding - use quotes
button('(click)'='onSave($event)') Save

// Mixed attributes with comma separation
input([value]='name', '(input)'='name = $event.target.value')

Structural Directives

Angular's structural directives like *ngIf, *ngFor require special handling. The asterisk prefix must be preserved within quotes to maintain proper Angular directive behavior:

// *ngIf - quote the directive
div(*ngIf='isVisible') Content here

// *ngFor - quote the directive
li(*ngFor='let item of items') {{ item.name }}

// Modern @if syntax (Angular 17+)
@if (isLoading) {
 <span>Loading...</span>
}

Angular binding syntax in Pug templates requires proper quoting to ensure Angular's template compilation works correctly.

Attribute Directives

Built-in and custom attribute directives work with proper quoting:

// ngClass and ngStyle
div('[ngClass]'='{ active: isActive }')
span('[ngStyle]'='{ color: textColor }')

// Two-way binding with ngModel
input('[(ngModel)]'='username')
Pug Mixins in Angular Templates
1//- Define a mixin for a button2mixin button(label, action)3 button.btn('(click)'=action)&attributes(attributes)= label4 5//- Use the mixin with different styles6+button('Save', 'saveItem()')(class="btn-primary")7+button('Cancel', 'cancelItem()')(class="btn-secondary")8+button('Delete', 'deleteItem()')(class="btn-danger")9 10//- Mixin for form fields11mixin form-field(label, model)12 .form-field13 label= label14 input('[ngModel]'=model, '(ngModelChange)'=model + ' = $event')15 16+form-field('Name', 'userName')17+form-field('Email', 'userEmail')

Migrating Existing Templates to Pug

Converting existing Angular HTML templates to Pug requires a systematic approach.

Using html2pug Tool

The html2pug tool automates much of the initial conversion from HTML to Pug. It parses existing HTML files and generates equivalent Pug syntax, handling most straightforward conversions automatically:

npm install -g html2pug
html2pug -f -c my-component.html

The -f flag prevents wrapping in html/body tags, and -c adds commas between attributes for Angular compatibility. However, the tool requires manual review and adjustment for Angular-specific syntax like bindings and directives.

Manual Conversion Patterns

Certain HTML patterns require manual conversion to achieve optimal Pug syntax:

Before (HTML):

<div class="card" *ngIf="showCard">
 <h3 [innerText]="title"></h3>
 <button (click)="onClick()">Click me</button>
</div>

After (Pug):

.card(*ngIf='showCard')
 h3('[innerText]'='title')
 button('(click)'='onClick()') Click me

Incremental Migration Strategy

Rather than converting all templates at once, an incremental approach reduces risk and allows teams to adapt gradually:

  1. Start new components in Pug
  2. Convert existing templates as they're modified
  3. Establish team conventions for mixins and includes
  4. Build tooling and IDE support

The html2pug conversion workflow helps streamline migration while maintaining Angular functionality.

Explore our web development services to learn how our team can assist with your Angular modernization initiatives.

Frequently Asked Questions

Conclusion

Integrating Pug into Angular projects offers meaningful advantages for template maintainability:

  • Cleaner syntax reduces boilerplate and improves readability
  • Mixins enable powerful template-level reuse across components
  • Smaller files improve navigation and reduce git diffs
  • Gradual migration minimizes risk and disruption to existing projects

The initial setup investment yields dividends through reduced boilerplate, clearer template structure, and powerful reuse mechanisms. For teams committed to template quality, Pug provides a compelling enhancement to the Angular development experience.

Getting Started

  1. Run ng add ng-cli-pug-loader to configure your project
  2. Create a new component with .pug template instead of .html
  3. Start using Pug syntax alongside Angular bindings and directives
  4. Establish team conventions for mixins, includes, and template organization

By combining Pug's elegant syntax with Angular's powerful framework, you can build more maintainable component templates while preserving all the reactive capabilities that make Angular powerful. The complete Pug and Angular integration guide provides additional patterns and best practices for your migration journey.

Looking to modernize your web development practices? Our team can help you implement modern tooling and best practices across your Angular projects.

Ready to Modernize Your Angular Development?

Our team specializes in Angular development with modern tooling and best practices. Let's discuss how we can help your project.