ngTemplate
Follow @dsheiko Star Fork DownloadngTemplate
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.
Motivation
- 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>
</div>
<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>
</select>
<div class="alert alert-danger" data-ng-if="!power.valid">
Power is required
</div>
</div>
<button type="submit" class="btn btn-default" data-ng-prop="'disabled', !form.valid">Submit</button>
</form>
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 foo.bar
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 );