8

Please help me on, How can we make AngularJS compile the code generated by directive ?

You can even find the same code here, http://jsbin.com/obuqip/4/edit

HTML

<div ng-controller="myController">
    {{names[0]}} {{names[1]}}
    <br/> <hello-world my-username="names[0]"></hello-world>
    <br/> <hello-world my-username="names[1]"></hello-world>
    <br/><button ng-click="clicked()">Click Me</button>
</div>

Javascript

var components= angular.module('components', []);
components.controller("myController",
    function ($scope) {
        var counter = 1;
        $scope.names = ["Number0","lorem","Epsum"];
        $scope.clicked = function() {
            $scope.names[0] = "Number" + counter++;
        };
    }
);

// **Here is the directive code**
components.directive('helloWorld', function() {
    var directiveObj =  {
        link:function(scope, element, attrs) {
            var strTemplate, strUserT = attrs.myUsername || "";
            console.log(strUserT);
            if(strUserT) {
                strTemplate = "<DIV> Hello" + "{{" + strUserT +"}} </DIV>" ;
            } else {
                strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
            }
            element.replaceWith(strTemplate);
        },
        restrict: 'E'
    };
    return directiveObj;
});

3 Answers 3

14

Here's a version that doesn't use a compile function nor a link function:

myApp.directive('helloWorld', function () {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      myUsername: '@'
    },
    template: '<span><div ng-show="myUsername">Hello {{myUsername}}</div>'
    + '<div ng-hide="myUsername">Sorry, No user to greet!</div></span>',
  };
});

Note that the template is wrapped in a <span> because a template needs to have one root element. (Without the <span>, it would have two <div> root elements.)

The HTML needs to be modified slightly, to interpolate:

<hello-world my-username="{{names[0]}}"></hello-world>

Fiddle.

Sign up to request clarification or add additional context in comments.

2 Comments

@Liviu, since the directive doesn't change the myUsername value, one-way databinding ('@') seems more appropriate than two-way databinding ('='). Although using '=' is easier (no need to use {{}} in the HTML), using '@' makes it clear that the directive does not need to modify the value.
@MarkRajcok, Excellent information in last comment, We would love to see some more like this be shared via blog or video tutorial. ;)
10

Code: http://jsbin.com/obuqip/9/edit

components.directive('helloWorld', function() {
    var directiveObj =  {
        compile:function(element, attrs) {
            var strTemplate, strUserT = attrs.myUsername || "";
            console.log(strUserT);
            if(strUserT) {
                strTemplate = "<DIV> Hello " + "{{" + strUserT +"}} </DIV>" ;
            } else {
                strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
            }
            element.replaceWith(strTemplate);
        },
        restrict: 'E'
    };
    return directiveObj;
});

Explanation: The same code should be used in compile function rather than linking function. AngularJS does compile the generated content of compile function.

2 Comments

Since element is not used in the link function version of this directive (Liviu's answser), I agree that a compile function seems better.
I just posted an answer that doesn't even need a compile function.
9

You need to create an angular element from the template and use the $compile service

jsBin

components.directive('helloWorld', ['$compile', function(compile) {
    var directiveObj =  {
        link: function(scope, element, attrs) {
            var strTemplate, strUserT = attrs.myUsername || "";
            console.log(strUserT);
            if (strUserT) {
                strTemplate = "<DIV> Hello" + "{{" + strUserT +"}} </DIV>" ;
            } else {
                strTemplate = "<DIV>Sorry, No user to greet!</DIV>" ;
            }

            var e = angular.element(strTemplate);
            compile(e.contents())(scope);
            element.replaceWith(e);
        },
        template: function() {
            console.log(args);
            return "Hello";
        },
        restrict: 'E'
    };
    return directiveObj;
}]);

4 Comments

stackoverflow.com/questions/12164138/…. Normally it's not an issue with 1:1 directive:html. ng-repeat and similar directives use the compile function to optimize.
This answer includes explanation from Misko stackoverflow.com/a/14359666/148869
@Liviu, what is the purpose of template: in the directive? Were you trying to see if you could generate the two versions of the output there (and found it didn't work and forgot to remove the code, maybe)? I'm curious to know if template: can take a function.
@MarkRajcok actually I just modified the OP's solution to include the compile service, frankly I didn't see the other parameters :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.