Advanced directives: workers, WASM, channels, viewport
AngularTS ships several advanced directives that expose modern browser APIs —
Web Workers, WebAssembly, Intersection Observer, and custom event channels —
directly in HTML without requiring JavaScript. These directives are registered
as part of the core ng module and are available in every AngularTS
application.
Controller and scope directives
ng-controller
Attaches a controller function to a section of the DOM, creating a new child scope populated by the controller.
<div ng-controller="TodoController as ctrl">
<p>{{ ctrl.title }}</p>
</div>
.controller('TodoController', ['$scope', function($scope) {
$scope.title = 'My Todos';
}]);
ng-scope
Assigns a stable name to the current scope so debugging tools and integration
code can find it later. The name is required. ng-scope does not create a child
or isolate scope.
<div ng-controller="UserController" ng-scope="userPanel">
<p>Hello {{ user.name }}</p>
</div>
ng-init
Initializes scope variables inline in the template. Best suited for simple one-off values or prototyping.
<div ng-init="name = 'World'; count = 0">
Hello {{ name }}, count is {{ count }}
</div>
Tip: Prefer controllers or services over
ng-initfor any real application logic.ng-initis ideal for zero-JS demos and quick prototypes.
DOM reference directives
ng-el
Use ng-el when you only need the native DOM element. It is the simple DOM
reference API and is usually the clearest choice for canvas, focus management,
layout measurement, and pointer-driven UI.
<section ng-controller="BoardController as $ctrl">
<canvas ng-el="$ctrl.boardEl"></canvas>
</section>
function BoardController() {
this.boardEl = null;
}
ng-el="$ctrl.boardEl" stores the element on the controller. Use this form with
controller-as syntax.
For simple scope shorthand, pass a bare name:
<canvas ng-el="boardEl"></canvas>
If the value is omitted, AngularTS uses the element id.
<canvas id="board" ng-el></canvas>
ng-ref
Use ng-ref when you need a component or directive controller reference, or
when you need to assign the reference to a full expression such as
$ctrl.child.
<search-box ng-ref="$ctrl.search"></search-box>
<button ng-click="$ctrl.search.clear()">Clear</button>
By default, ng-ref reads the component or element-directive controller when
one exists, and falls back to the DOM element.
ng-ref-read is not a standalone directive. It only changes what ng-ref
assigns.
<canvas ng-ref="$ctrl.boardEl" ng-ref-read="$element"></canvas>
<my-widget ng-ref="$ctrl.resizeHandle" ng-ref-read="resizeHandle"></my-widget>
Use ng-ref-read="$element" only when you specifically need the DOM element
through an assignable expression. For the common DOM-only case, prefer ng-el.
function BoardController() {
this.boardEl = null;
}
Event and communication directives
ng-channel
Subscribes to a named event channel (backed by $eventBus). When an event is
published on the channel, the expression is evaluated.
<div>Latest: {{ lastNotification }}</div>
ng-listener
Attaches a DOM event listener to the element using the native addEventListener
API — without the overhead of Angular’s event directive wiring.
<div>Scroll-tracked content</div>
ng-inject
Injects a named service directly into the scope, making it accessible in the template without a controller.
<div ng-inject="$http">
<!-- $http is now available in this scope -->
</div>
Lazy loading and performance
ng-viewport
Uses the browser’s Intersection Observer API to run expressions when an element enters or leaves the viewport. Ideal for below-the-fold loading, lazy request triggers, analytics markers, and canvas/chart initialization.
<div
ng-viewport
on-enter="loadComments($entry)"
on-leave="visible = false"
data-viewport-threshold="0.5"
data-viewport-margin="200px 0px"
>
<div ng-repeat="comment in comments">{{ comment.text }}</div>
</div>
Use data-viewport-once when the enter expression should run only once:
<div ng-viewport data-viewport-once on-enter="loadOnce($entry)"></div>
ng-viewport
- Type: marker attribute
Supported attributes:
| Attribute | Description |
|---|---|
on-enter | Expression evaluated when the element intersects the viewport. |
on-leave | Expression evaluated when the element stops intersecting. |
data-viewport-threshold | Intersection threshold, such as 0.5 or 0, 0.5, 1. |
data-viewport-margin | Root margin passed to IntersectionObserver, such as 200px 0px. |
data-viewport-once | Disconnects the observer after the first enter callback. |
on-enter and on-leave receive $entry and $entries locals from the
Intersection Observer callback.
ng-cloak
Prevents the browser from briefly displaying uncompiled template syntax
({{ }}) before AngularTS bootstraps. Add to the root element or any element
with interpolation.
<div ng-cloak>
<p>Hello {{ user.name }}</p>
</div>
Note: Always include the CSS rule
[ng-cloak] { display: none; }in your stylesheet when usingng-cloak.
Web Workers and WebAssembly
ng-worker
Runs a JavaScript file in a Web Worker and binds the result back to scope. The
worker communicates via postMessage.
<div
ng-worker="/workers/sort.js"
data-params="{ items: largeList }"
on-result="sortedItems = $result"
>
<div ng-repeat="item in sortedItems">{{ item.name }}</div>
</div>
ng-worker
- Type:
string - Required: yes
Path to the Web Worker JavaScript file.
Use an empty ng-worker with data-handle="name" to reuse a worker registered
through app.worker(name, script). Shared handles are application-owned rather
than terminated with the directive scope.
data-params
- Type:
expression
Data to pass to the worker as the message payload.
on-result
- Type:
expression
Expression evaluated when the worker posts a result. $result contains the
worker’s response.
Worker results are not inserted as HTML when this expression is absent.
data-request
- Type:
boolean data attribute
Use the standard correlated request protocol instead of consuming every stream message. This is the preferred mode for shared workers.
interval
- Type:
number
Re-send the params to the worker on a millisecond interval.
throttle
- Type:
number
Throttle worker invocations to at most once per N milliseconds.
The worker file uses standard onmessage / postMessage:
var sorted = e.data.items.slice().sort((a, b) => a.name.localeCompare(b.name));
postMessage(sorted);
};
ng-wasm
Loads a WebAssembly module and makes its
WasmResource available on
scope.
<div ng-wasm src="/wasm/math.wasm" as="math"></div>
<p>
Result: {{ math.status === 'ready' ? math.exports.add(3, 4) : 'Loading...' }}
</p>
ng-wasm
- Type:
string - Required: yes
Path to the .wasm file to load.
as
- Type:
string
Scope property name to assign the
WasmResource to. Defaults to
wasm. The reserved object keys __proto__, constructor, and prototype are
rejected.
Transclusion
ng-transclude
Used inside custom directive templates to mark where transcluded content should be inserted.
return {
transclude: true,
template: '<div class="panel"><ng-transclude></ng-transclude></div>'
};
});
<my-panel>
<p>This content is transcluded into the panel.</p>
</my-panel>
Non-bindable sections
ng-non-bindable
Prevents AngularTS from compiling or interpolating a subtree. Use this for displaying raw Angular syntax as documentation or code examples.
<pre ng-non-bindable>
{{ this will not be interpolated }}
ng-repeat="item in items"
</pre>
Aria directives
AngularTS automatically manages ARIA attributes for accessibility. These directives are applied alongside their functional counterparts:
| Directive | ARIA attribute managed |
|---|---|
ng-disabled | aria-disabled |
ng-checked | aria-checked |
ng-readonly | aria-readonly |
ng-required | aria-required |
ng-show / ng-hide | aria-hidden |
ng-model | aria-value*, role |
The $aria service and module config let you configure which ARIA attributes
are automatically managed:
angular.createModule('app', []).config({
$aria: {
ariaDisabled: true,
ariaChecked: true,
ariaReadonly: true,
ariaRequired: true,
ariaHidden: true,
ariaValue: true,
tabindex: true,
},
});
Event directives
AngularTS generates event directives for all common DOM events. They all follow
the ng-<eventname>="expression" pattern:
| Directive | DOM event |
|---|---|
ng-click | click |
ng-dblclick | dblclick |
ng-focus | focus |
ng-blur | blur |
ng-keydown | keydown |
ng-keyup | keyup |
ng-mouseenter | mouseenter |
ng-mouseleave | mouseleave |
ng-mousemove | mousemove |
ng-mouseover | mouseover |
ng-mousedown | mousedown |
ng-mouseup | mouseup |
ng-submit | submit (on forms) |
ng-cut | cut |
ng-copy | copy |
ng-paste | paste |
ng-load | load |
The expression is evaluated in the current scope. $event refers to the native
DOM event object:
<input ng-keydown="$event.key === 'Enter' && submit()" />
Event policy can be declared once on the same element and applies to generated event directives on that element:
<div
ng-click="$ctrl.activate($event)"
data-event-prevent
data-event-capture
></div>
Supported policy attributes:
| Attribute | Behavior |
|---|---|
data-event-prevent | Calls $event.preventDefault() first |
data-event-stop | Calls $event.stopPropagation() first |
data-event-capture | Registers the listener with capture: true |
data-event-once | Registers the listener with once: true |
data-event-passive | Registers the listener with passive: true |
data-event-passive cannot be combined with data-event-prevent, because
passive listeners cannot cancel default browser behavior.
ng-pointer-capture can be combined with an application directive that installs
native pointer listeners for game and board interactions:
<div ng-pointer-capture pointer-drag></div>
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.