AngularJS1 directive with `terminal:true` will disable rendering of expressions, why?

AngularJS1 directive with `terminal:true` will disable rendering of expressions, why?

angularjs compile
angularjs compile dynamic html
angularjs directive scope
angularjs compile example
angular scope variable not updating in view
angularjs directive link
angularjs directive require
angularjs-directive replace

HTML code:

<div ng-controller="MyController">
    <div>{{ hello }}</div>
    <div my-terminal>{{hello}}</div>
</div>

JS code:

const app = angular.module('app', [])

app.controller('MyController', function ($scope) {
    $scope.hello = 'Hello, AngularJS'
})

app.directive('myTerminal', function () {
    return {
        restrict: 'A',
        terminal: true,
        link: function () {
            console.log('--- myTerminal')
        }
    }
})

Please notice the terminal is true.

Result:

From angularjs document, I found when terminal is true, any other directives applied on the same element with lower priority will not be executed, but I can't explain why <div my-terminal>{{hello}}</div> will not render the expression {{hello}}

A small complete demo for this question: https://github.com/freewind-demos/angularjs1-directive-terminal-issue-demo


From the Docs:

terminal

If set to true then the current priority will be the last set of directives which will execute (any directives at the current priority will still execute as the order of execution on same priority is undefined). Note that expressions and other directives used in the directive's template will also be excluded from execution.

AngularJS Comprehensive Directive API Reference - terminal

A better explaination of what that means comes from the Docs for ng-non-bindable which uses the terminal property:

ngNonBindable

The ngNonBindable directive tells AngularJS not to compile or bind the contents of the current DOM element, including directives on the element itself that have a lower priority than ngNonBindable. This is useful if the element contains what appears to be AngularJS directives and bindings but which should be ignored by AngularJS. This could be the case if you have a site that displays snippets of code, for instance.

AngularJS ng-non-bindable Directive API Reference

AngularJS1 directive with `terminal:true` will disable rendering of , AngularJS1 directive with `terminal:true` will disable rendering of why <div my-​terminal>{{hello}}</div> will not render the expression {{hello}}. AngularJS Element Directives : Show and Hide and Remove Directives The AngularJS provides a set of directives to set the CSS styles and other appearances of the Elements in the Document. These Directives style the elements dynamically to reflect the changes within the Data Model.A List of such Directives are shown Below.


https://github.com/angular/angular.js/blob/master/src/ng/compile.js :

function addTextInterpolateDirective(directives, text) {
      var interpolateFn = $interpolate(text, true);
      if (interpolateFn) {
        directives.push({
          priority: 0,
          compile: function textInterpolateCompileFn(templateNode) {
            var templateNodeParent = templateNode.parent(),
                hasCompileParent = !!templateNodeParent.length;
...

So using expression {{}} results in adding directive. Guess thats why it is affected by 'terminate' property.

AngularJS: API: $compile, You can either return a Directive Definition Object (see below) that defines the terminal. If set to true then the current priority will be the last set of directives which will The expression is evaluated in the context of the parent scope. calling the transclude function to get the DOM and calling element.remove() to remove it),  With angular that is not the case. Since angular has concept of directives, a directive may unroll a loop, which can the instantiate a controller, which can than modify the model which then causes more DOM updates. This makes it hard to have clear line in a send as to where the DOM update begins and ends.


You need to use ng-bind

<div ng-controller="MyController">
  <div>{{hello}}</div>
  <div my-terminal ng-bind="hello"></div>
</div>

The DEMO

const app = angular.module('app', [])

app.controller('MyController', function ($scope) {
    $scope.hello = 'Hello, AngularJS'
})

app.directive('myTerminal', function () {
    return {
        restrict: 'A',
        terminal: true,
        link: function () {
            console.log('--- myTerminal')
        }
    }
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="MyController">
    <div>{{ hello }}</div>
    <div my-terminal ng-bind="hello"></div>
</body>

HTML Compiler, This makes the scope model the single source of truth. A directive is just a function which executes when the compiler encounters it in the DOM. At runtime the ngRepeat watches the expression and as items are added to the array it clones the <li> This will not render properly, unless we do some scope magic. The first  AngularJS comes with a set of these directives built-in, like ngBind, ngModel, and ngClass. Much like you create controllers and services, you can create your own directives for AngularJS to use. When AngularJS bootstraps your application, the HTML compiler traverses the DOM matching directives against the DOM elements.


Top 18 Most Common AngularJS Mistakes That Developers Make , In this article you will learn about most common AngularJS developer mistakes and One of them is disabling debug info. DebugInfoEnabled is a setting which defaults to true, and allows for scope Many directives create child scopes such as ngRepeat , ngIf , and ngController . applyAsync() on the expressions instead. to render the image as if it was an image. The comments are also massively increasing the size of the string. I've attempted to remove the comments, but I still cannot work out a way to extract the rendered HTML without angular directives polluting it. Ideally, when I call innerHTML I wanted to see if the


Upgrading from AngularJS to Angular, This attribute is also deprecated in AngularJS. priority and terminal . This is true whether the event originated in AngularJS or Angular code. You can remove the ng-app and ng-strict-di directives from the HTML and instead switch to you can take advantage of lazy loading to load, bootstrap, and render the AngularJS​  Matching Directives. Before we can write a directive, we need to know how AngularJS's HTML compiler determines when to use a given directive.. Similar to the terminology used when an element matches a selector, we say an element matches a directive when the directive is part of its declaration.


NgIf, When the expression evaluates to true, Angular renders the template provided A shorthand form of the directive, *ngIf="condition" , is generally used, provided  Here Mudassar Ahmed Khan has explained with an example, how to enable or disable Button when CheckBox is checked or unchecked in AngularJS. This article will illustrate how to enable or disable Button on CheckBox click i.e. checked – unchecked or selected – unselected using ng-disabled directive in AngularJS.