Follow @dsheiko Star Fork Download

ngTemplate is a light-weight DOM-based template engine, inspired by AngularJS.

mustache.js, Handlebars or _.template are all nice and shiny, until it comes to a form. With every rending these template engines replace the bound DOM subtree and the state of inputs gets lost.

ngTemplate treats the DOM carefully. It modifies the exact target nodes gracefully according to the directives and actual state.


  • Progressive enhancement friendly: Server-side generated HTML can be fully ready for presentation. During ngTemplate synchronization it will be updated according to element directives and a provided state
  • HTML compliant: data-* - directives instead of foreign concepts such as {{foo}}, [hidden], *ngFor, [(ngModel)]
  • Concern separation: Presentation state logic decoupled from the view
  • Performance: ngTemplate modifies DOM nodes by state diff; it touches the DOM only when it's necessary
  • Easy to catch up: Familiar for Angular folks directives such as data-ng-if, data-ng-switch, data-ng-for and a few extra intuitive e.g. data-ng-text, data-ng-class
  • Really small library: minimized gziped size is 4K
  • Definitely Typed: IDE checks on the fly if you violate any of declared interfaces (if not the compiler does)

How does it work?

Templates are written with HTML that contains ngTemplate-specific data attributes (data-ng-*):

<form id="heroForm" novalidate>
  <div class="form-group">
    <label for="name">Name</label>
    <input id="name" type="text" class="form-control" required >
    <div class="alert alert-danger" data-ng-if="!name.valid">
      Name is required
  <div class="form-group">
    <label for="power">Hero Power</label>
    <select id="power" class="form-control"  required>
      <option data-ng-for="let p of powers" data-ng-text="p" >Nothing here</option>
    <div class="alert alert-danger" data-ng-if="!power.valid">
      Power is required
   <button type="submit" class="btn btn-default" data-ng-prop="'disabled', !form.valid">Submit</button>

ngTemplate synchronizes the template with the passed state. Let's say we have the template HTML within a DOM element, so we initialize the template like let template = new NgTemplate( el );. Alternatively we can populate the bounding element with the template from the passed string: let template = new NgTemplate( el, '<i data-ng-if="foo">Hello!</i>' );

As soon as we have template object we can sync it to a specified scope. E.g. template.sync({ foo: true }); makes variable foo available for template expressions, template.sync({ foo: { bar: true }}); gets accessable as

import { NgTemplate } from "ng-template";

let el = document.querySelector( "#heroForm" ),
    elName = document.querySelector( "#name" ),
    elPower = document.querySelector( "#power" );

// Bind the template
let template = new NgTemplate( el );

// Set the scope (view state)
let scope = {
  powers: [ "-", "Really Smart", "Super Flexible",
            "Super Hot", "Weather Changer" ],
  power: {
    valid: true
  name: {
    valid: true
  form: {
    valid: false
// Sync to the scope
template.sync( scope );

Live Demo

ngTemplate Demo: Hero

results matching ""

    No results matching ""