Angular Directives – compile & link & trusted HTML

Wednesday Nov 13, 2019

Let’s look some more into on Angular directives

Directive

Here’s a simple directive with a couple of scope variables that get displayed:

class="main-div">
  
ng-controller="MyCtrl">
    Hello, {{name}}!
    
list="osList" hello-directive>

Here is the angular stuff:

/**
 * Shows how to modify the original element in compile
 * to add a class to the DOM.
 */
var myApp = angular.module('myApp', []);
 
var HelloDirective = function($sce) {
    return {
      scope: {
        list: "="
      }, // use a new isolated scope
      restrict: 'AE',
      replace: false,
      template: '
',
      compile: function(tElem, attrs) {
 
        var ul = document.createElement("ul");
        var li = document.createElement("li")
        li.innerHTML = "";
        ul.appendChild(li);
 
        var baseElem = tElem[0];
        baseElem.className ? baseElem.className += " compiled-element" : baseElem.className = "compiled-element";
        baseElem.appendChild(ul);
        console.log(tElem);
 
        return function(scope, elem, attrs) {
          scope.list = $sce.trustAsHtml("Link function value, too");
          console.log(scope.list);
        }
      }
    };
  }
 
myApp.directive("helloDirective", HelloDirective);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
 
myApp.controller('MyCtrl', function($scope) {
  $scope.name = 'Angular Directive';
  $scope.osList = "Original value";
});

Here is a fiddle for the example, which has some css and things. Nothing really special here. http://jsfiddle.net/mbaranski/6h1frt52/

Now, in order to make some DOM changes, we can’t change the element during the link function. If you want to change the element, you have to do it during the compile function. The compile function gets called when the directive is created, and should return the link function. This allows the directive to be modified. This example shows how to add a list to the directive.

We can also add some HTML with the “sce” module:

/**
 * Shows how to modify the original element in compile
 * to add a class to the DOM.
 */
var myApp = angular.module('myApp', []);
 
var HelloDirective = function($sce) {
    return {
      scope: {
        list: "="
      }, // use a new isolated scope
      restrict: 'AE',
      replace: false,
      template: '
',
      compile: function(tElem, attrs) {
 
        var ul = document.createElement("ul");
        var li = document.createElement("li")
        li.innerHTML = "";
        ul.appendChild(li);
 
        var baseElem = tElem[0];
        baseElem.className ? baseElem.className += " compiled-element" : baseElem.className = "compiled-element";
        baseElem.appendChild(ul);
        console.log(tElem);
 
        return function(scope, elem, attrs) {
          scope.list = $sce.trustAsHtml("Link function value, too");
          console.log(scope.list);
        }
      }
    };
  }
  /**
  var p = document.createElement("p");
        p.innerHTML = "asdddf";
        var ul = document.createElement("ul");
        var li = document.createElement("li")
        li.innerHTML = "List Item";
        ul.appendChild(li);
        elem.append(p);
        elem.append(ul);
   */
myApp.directive("helloDirective", HelloDirective);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
 
myApp.controller('MyCtrl', function($scope) {
  $scope.name = 'Angular Directive';
  $scope.osList = "Original value";
});

The interesting thing there is the compile function. The compile function gets the tElem, which is the template element itself. This function is run when the directive is compiled, and there is no scope available. We can, however, add some elements to the directive. Note that the compile function returns the link function.

Here is a working fiddle - http://jsfiddle.net/mbaranski/ous4yrkn/

Here’s a final fiddle showing how to add a list to the element’s div - http://jsfiddle.net/mbaranski/46dd6p1p/