2

I'm using directive to display html snippets.

And templateUrl inside the directive, to be able to include snippets as html file.

The directive does not work, if I try to call inside a builtin ng-repeat directive ({{snip}} is passed as is, without substitute):

div ng-repeat="snip in ['snippet1.html','snippet2.html']">
  <my-template snippet="{{snip}}"></my-template>
</div>

For reference, here is the directive:

app.directive("myTemplate", function() {
return {
    restrict: 'EA',
    replace: true,
    scope: { snippet: '@'},
    templateUrl: function(elem, attrs) {
      console.log('We try to load the following snippet:' + attrs.snippet);
      return attrs.snippet;
    }
  };
});

And also a plunker demo.

Any pointer is much appreciated. (the directive is more complicated in my code, I tried to get a minimal example, where the issue is reproducible.)

arcol
  • 1,510
  • 1
  • 15
  • 20

5 Answers5

1

Check out this link

http://plnkr.co/edit/TBmTXztOnYPYxV4qPyjD?p=preview

app.directive("myTemplate", function() {
  return {
    restrict: 'EA',
    replace: true,
    scope: { snippet: '=snippet'},
    link: function(scope, elem, attrs) {
      console.log('We try to load the following snippet:' + scope.snippet);
    },
    template: '<div ng-include="snippet"></div>'
  };
})
Rajeshwar
  • 2,290
  • 4
  • 31
  • 41
  • You are not including the **content** of the html snippets, rather you are displaying the **filename** of the html snippets. Can you adapt your solution to include the content of the snippets? – arcol Feb 10 '15 at 08:14
  • @arcol, Please check the same plunker link, the changes you mentioned are implemented. – Rajeshwar Feb 10 '15 at 08:51
  • ng-include will create isolated scope again – Pankaj Parkar Feb 10 '15 at 10:48
1

attrs param for templateUrl is not interpolated during directive execution. You may use the following way to achieve this

app.directive("myTemplate", function() {
  return {
    restrict: 'EA',
    replace: false,
    scope: { snippet: '@'},
    template: '<div ng-include="snippet"></div>'
  };
}); 

Demo: http://plnkr.co/edit/2ofO6m45Apmq7kbYWJBG?p=preview

Asik
  • 7,967
  • 4
  • 28
  • 34
  • This **is** a workaround. The final DOM looks like this: `
    ` the contant of my snippet `
    `. Thank you for the idea.
    – arcol Feb 10 '15 at 07:23
  • @Doug, Rajeshwar and you gave basically identicaly solution. I'm marking your response as solution, because you are using one way databinding (@), instead of two way databinding (=) or $observe, so It is slightly more elegant. A small modification `'@'` should be `'@snippet'`, the directive only needs this variable from its parent scope. I don't like the fact, the template file is embedded in the DOM tree two additional level deep. But pankajparkar solution is maybe overkill. – arcol Feb 10 '15 at 14:24
  • I ended up modifying these two lines: `scope: { snippet: '@snippet'},` and `template: '
    '`. Could you please update your answer, and also include everything from [plunker](http://plnkr.co/edit/kEaIF7INQTezSl48pNv8?p=info) for archiving reasons? (html, js, two snippets)
    – arcol Feb 10 '15 at 15:12
0

You can use ng-include, watching the attrs. Like this:

app.directive("myTemplate", function() {
    return {
        restrict: 'E',
        replace: true,
        link: function(scope, elem, attrs) {
            scope.content = attrs.snippet;
            attrs.$observe("snippet",function(v){
                scope.content = v;
            });
        },
        template: "<div data-ng-include='content'></div>"
    };
});
Doug
  • 195
  • 1
  • 1
  • 13
0

Just made changes in directive structure. Instead of rendering all templates using ng-repeat we will render it using directive itself, for that we will pass entire template array to directive.

HTML

<div ng-init="snippets = ['snippet1.html','snippet2.html']">
    <my-template snippets="snippets"></my-template>
</div>

Directive

angular.module('myApp', [])
.controller('test',function(){})
    .directive("myTemplate", function ($templateCache, $compile) {
    return {
        restrict: 'EA',
        replace: true,
        scope: {
            snippets: '='
        },
        link: function(scope, element, attrs){
            angular.forEach(scope.snippets, function(val, index){
                //creating new element inside angularjs
                element.append($compile($templateCache.get(val))(scope));
            });
        }
    };
});

Working Fiddle

Hope this could help you. Thanks.

Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • It was not specified in the original request, but I would like the html snippets in separate files. Which looks regular html and can be edited by a third party (ie. web designer). Reading [$templateCache](https://docs.angularjs.org/api/ng/service/$templateCache) documentation, you either use $templateCache.put with a string, or you put the template in the main html via ` – arcol Feb 10 '15 at 07:15
  • @arcol you are correct and also you can put in `html` too..only you need to put those html template to `$templateCache` at the run phase of angular. refer this http://stackoverflow.com/questions/27785564/run-a-function-after-all-partials-ng-includes-loaded/27786046#27786046 – Pankaj Parkar Feb 10 '15 at 07:23
  • You need to do only this `app.run(['$templateCache','$q','$http', function($templateCache, $http){ $http.get('partials/views/template1.html',{ cache : $templateCache }); $http.get('partials/views/template2.html',{ cache : $templateCache }); }]);` to put html inside `$templateCache` – Pankaj Parkar Feb 10 '15 at 07:29
  • I tried to get it work with your solution, but I got stuck: http://plnkr.co/edit/IYZHcmSkX7zkM9o0NEFe – arcol Feb 10 '15 at 08:58
0

it seems you are trying to have different views based on some logic and you used templateUrl function but Angular interpolation was not working, to fix this issue

don't use templateUrl

so how to do it without using templateUrl

simply like this

app.directive("myTemplate", function() {
    return {
        link: function(scope, elem, attrs) {
           $scope.templateUrl = '/ActivityStream/activity-' + $scope.ativity.type + '.html'
        },
        template: "<div data-ng-include='templateUrl'></div>"
    };
});

hope this is simple and esay to understand

Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92