Reputation: 6347
I'm developing Timesheet application. I have ready layout (html/css). Currently I'm working on layout behavior. My current goal is extracting timesheet table header in directive. Angular template html should look similar to this:
<colgroup class="col_day">
<col ng-repeat="day in header.days" ng-class="someConditions">
</colgroup>
<thead>
<tr>
<th ng-repeat="day in header.days" ng-class="someConditions">
{{someLayout}}
</th>
</tr>
</thead>
I want to use this template via directive like this:
<table>
<timesheet-header></timesheet-header>
<tbody></tbody>
<tfoot></tfoot>
</table>
Problems:
I have only bad solutions:
Note: I'm using AngularJS v1.4.3. Debugging in latest Google Chrome.
Upvotes: 2
Views: 1037
Reputation: 943
"Create two different directives for colgroup and thead (this solves multiple roots, but html will still appear outside table tag)" - You can find more details for this behavior in https://github.com/angular/angular.js/issues/1459. And specifically in https://github.com/angular/angular.js/issues/1459#issuecomment-67235182
You can solve this issue using transclude and custom directive for table as attribute
http://plnkr.co/edit/8JptrwUcA0pPl9xB9yZQ?p=preview
<table my-table>
<tbody>
<tr>
<td>4</td>
<td>5</td>
</tr>
</tbody>
</table>
.directive('myTable', [function() {
return {
restrict: 'A',
transclude: true,
template: '<table>' +
'<colgroup class="col_day"><col ng-repeat="n in [1, 2] track by $index">{{n}}</col></colgroup>' +
'<thead>' +
'<tr>' +
'<th ng-repeat="n in [1, 2] track by $index"> {{n}}</th>' +
'</tr>' +
'</thead>' +
'<div ng-transclude></div>' +
'</table>'
};
}])
Upvotes: 0
Reputation: 1162
Okay, so the attribute directive was in fact the right way to go, it just took a little bit to realize how the changes to transclude work in newer versions of Angular.
So, with the newer versions of Angular, ng-transclude actually removes everything inside of the directive. It turns out though that when you use the transclude option on your directive, Angular actually exposes a function to you in the link function that allows you to manually handle the transcluded content. Once you have this, you can tell it to simply append the content instead of replace it like it does by default.
Some good reading on the subject can be found here: http://ng.malsup.com/#!/transclude-function
template:
<table>
<colgroup class="col_day">
<col ng-repeat="day in header.days" ng-class="someConditions">
</colgroup>
<thead>
<tr>
<th ng-repeat="day in header.days" ng-class="someConditions">
{{someLayout}}
</th>
</tr>
</thead>
</table>
directive:
app.directive('timesheetHeader', function() {
return {
restrict: 'A',
replace: true,
transclude: true,
templateUrl: 'timesheet-header.template.html',
link: function(scope, el, attrs, ctrl, transcludeFn) {
var transcludedContent = transcludeFn();
el.append( transcludedContent );
}
};
});
Actual HTML Code:
<table timesheet-header>
<tbody>
<tr>
<td>Hello</td>
<td>world!</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
Upvotes: 1