Sarp
Sarp

Reputation: 105

Build template string inside directive

I'm trying to build a string of HTML code inside the directive and then use that as the directive's template.

I tried this but it doesn't work.

myApp.directive('myDirective', [function() {
    return {
        restrict: 'E',
        scope: {
           data: '='      // this is the data that will shape the HTML
        },
        template: str,
        controller: function($scope){
            $scope.str = ****BUILD THE STRING HERE USING 'data'****
        }
    };
}]);

Then I tried passing the app's scope to the directive, but got an error again

myApp.directive('myDirective', ['$scope', function($scope) {
    var str = ****BUILD THE STRING HERE USING $scope.data****
    return {
        restrict: 'E',
        template: str
    };
}]);

I'm confused about how I can do this. In the first example the string is built correctly and when I do

template: {{str}}

I see the string but obviously, it just shows up as text on the page and it's not interpreted as HTML code.

Is there a way to access either myApp's or the directive controller's scope within the return statement of the directive?

I could build the string outside of the directive, but even if I do that I still can't access myApp's scope within the directive.

Upvotes: 2

Views: 1480

Answers (2)

Chris Halcrow
Chris Halcrow

Reputation: 32050

Strictly speaking what you're trying to do can be achieved by using ng-if to output html that uses different directives based on the data count in your controller. This is better 'separation of concerns', as it means you're moving your presentation logic into the view where it belongs, and your controller is then concerned with your business logic including a data count variable (which you can then use in the ng-if).

If using this approach, you'll want to put your data retrieval into a service that the controller uses, and use the same controller for both directives.

Upvotes: 0

Alon Eitan
Alon Eitan

Reputation: 12025

Directives, by nature have access to the outer scope, if you don't strictly define it with an inner scope (or isolated scope). Example:

angular.module('app',[]).controller('ctrl', function($scope) {
  $scope.example = {
    message: "Hello world"
  };
}).directive("myDirective", function() {
  return {
    template: '<strong>{{example.message}}</strong>'
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div my-directive></div>
</div>

As you can see in the example above - The directive "knows" the outer scope values without you need to actually inject it.

Now, you can create an isolated scope and by doing this you don't limit yourself to a given scope:

 angular.module('app',['ngSanitize']).controller('ctrl', function($scope) {
  $scope.example = {
    html: "<strong>Hello world</strong>"
  };
}).directive("myDirective", function() {
  return {
    scope: {
      data: '='
    },
    template: '<div ng-bind-html="data"></div>'
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-sanitize.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div my-directive data="example.html"></div>
</div>

By including ngSanitize I an able to use the ngBindHtml directive and pass an HTML structure to the directive inner scope.

Upvotes: 1

Related Questions