I am using directives to try to replace some of the often-reoccurring template code that i must write with something simpler.
lets say I have the following original markup:
<!-- section with repeating stuff in it -->
<div some-attributes etc="etc" very-long-tag="true">
<p class="lead">Some description text</p>
<div class="row section short" ng-repeat="row in things">
<div class="col-sm-6 col-md-4" ng-repeat="app in row.col">
<div class="thumbnail">
<img ng-src="im/things/{{app.image}}" alt="..." class="img-circle" width="250">
<div class="caption">
<h3>{{app.name}}</h3>
<p>{{app.desc}}</p>
</div>
</div>
</div>
</div>
</div>
and I want to simplify it by doing something like this:
<!-- section with repeating stuff in it -->
<xx title="Some description text">
<!-- this innerHTML gets passed to the directive -->
<div class="row section short" ng-repeat="row in things">
<div class="col-sm-6 col-md-4" ng-repeat="app in row.col">
<div class="thumbnail">
<img ng-src="im/things/{{app.image}}" alt="..." class="img-circle" width="250">
<div class="caption">
<h3>{{app.name}}</h3>
<p>{{app.desc}}</p>
</div>
</div>
</div>
</div>
<!-- end of innerHTML -->
</xx>
...where there are a several attributes that can be used to shorten the overall block, the directive is currently written this way:
_d.directive('xx', function() {
return {
scope: {
'color': '=',
'option': '=',
'title': '=',
'image': '=',
'image-pos': '=',
'image-size': '='
},
restrict: 'E',
transclude: false,
template: function(element, scope) {
var inside = 'x';
var content = element[0].innerHTML;
var title = scope.title;
var color = scope.color ? 'style="background-color: '+scope.color+'"' : "";
var title = scope.title ? '<h2 class="centertext marginBottom20">'+scope.title+'</h2>' : '';
return ['<div class="section row short" '+color+' ng-transclude>',
title,
content, //this may contain {{template code}}, but it always gets omitted
'</div>'
].join("\n");
},
};
});
The problem is that the existing HTML always gets omitted if it contains any {{angular template code}}
.
How do I write the directive so that it still honors the template code?
I am using directives to try to replace some of the often-reoccurring template code that i must write with something simpler.
lets say I have the following original markup:
<!-- section with repeating stuff in it -->
<div some-attributes etc="etc" very-long-tag="true">
<p class="lead">Some description text</p>
<div class="row section short" ng-repeat="row in things">
<div class="col-sm-6 col-md-4" ng-repeat="app in row.col">
<div class="thumbnail">
<img ng-src="im/things/{{app.image}}" alt="..." class="img-circle" width="250">
<div class="caption">
<h3>{{app.name}}</h3>
<p>{{app.desc}}</p>
</div>
</div>
</div>
</div>
</div>
and I want to simplify it by doing something like this:
<!-- section with repeating stuff in it -->
<xx title="Some description text">
<!-- this innerHTML gets passed to the directive -->
<div class="row section short" ng-repeat="row in things">
<div class="col-sm-6 col-md-4" ng-repeat="app in row.col">
<div class="thumbnail">
<img ng-src="im/things/{{app.image}}" alt="..." class="img-circle" width="250">
<div class="caption">
<h3>{{app.name}}</h3>
<p>{{app.desc}}</p>
</div>
</div>
</div>
</div>
<!-- end of innerHTML -->
</xx>
...where there are a several attributes that can be used to shorten the overall block, the directive is currently written this way:
_d.directive('xx', function() {
return {
scope: {
'color': '=',
'option': '=',
'title': '=',
'image': '=',
'image-pos': '=',
'image-size': '='
},
restrict: 'E',
transclude: false,
template: function(element, scope) {
var inside = 'x';
var content = element[0].innerHTML;
var title = scope.title;
var color = scope.color ? 'style="background-color: '+scope.color+'"' : "";
var title = scope.title ? '<h2 class="centertext marginBottom20">'+scope.title+'</h2>' : '';
return ['<div class="section row short" '+color+' ng-transclude>',
title,
content, //this may contain {{template code}}, but it always gets omitted
'</div>'
].join("\n");
},
};
});
The problem is that the existing HTML always gets omitted if it contains any {{angular template code}}
.
How do I write the directive so that it still honors the template code?
Share Improve this question asked Apr 9, 2014 at 18:36 KristianKristian 21.9k19 gold badges108 silver badges184 bronze badges 4- Any reason your not using transclude? Also any reason your building your HTML in a JS String instead of having static HTML with angular bindings? – rob Commented Apr 9, 2014 at 20:28
-
yes and yes. transclude has and has not been used, it didn't do what I expected either way, so I figured someone with transclude expertise would say something in response to this question. js string instead of angular binding: i was just doing this so i could write conditions outside of the template code. but also, in the context of angular, i'm not sure if you mean bindings as in using
ng-bind
or bindings in the sense that i should use{{bindings}}
. can you show me an example of what you'd do here... as an answer? – Kristian Commented Apr 9, 2014 at 21:50 - Take a look at the eggheadIO video on ponents and containers: egghead.io/lessons/angularjs-ponents-and-containers John's example of containers seems like it would do what you need. – rob Commented Apr 10, 2014 at 13:58
- thanks for the video, it was just enough information that I needed in order to start asking the right questions. – Kristian Commented Apr 11, 2014 at 16:18
1 Answer
Reset to default 5Ive successfully fixed the issue with the directive, but it took several steps.
Use the correct scope properties. instead of using
'='
, I used'@'
That was based on the following link: What is the difference between '@' and '=' in directive scope in AngularJS?
The thing to note about scope isolation using
@
,=
, and&
affects the way you must refer to the variable in the template. for example, using=
means that I would refer the variable withoutbrackets
while using@
would refer to the variable with{{brackets}}
.Like I mentioned in the first point, after adjusting the scope properties, i needed to go back and refer to the variables in the correct way depending on how the scope was defined.
ng-transclude
when used with{...transclude: true,...}
requires that I actually put a container somewhere in the template for that transcluded content. Here's an example of that:return ['<div class="section row short" '+color+' ng-transclude>', title, '<div ng-transclude>', //this is the container for the original innerHTML, transcluded content, //this may contain {{template code}}, and gets transcluded '</div> '</div>' ].join("\n");
Only then did the directive work as expected. Also, props to @rob for providing me with this introductory link, https://egghead.io/lessons/angularjs-ponents-and-containers.