I have two components. The first one represents a table of items and the second one represents one item. The first one is repeating the second one many times.
The List Component (app-list
):
<table>
<tr *ngFor="let item of items" [item]="item" app-item></tr>
</table>
The Item Component (app-item
):
<td>
<img src="https://someimage.com/{{item.img}}.jpg">
</td>
<td>
<h3>{{item.name}}</h3>
</td>
<td>
{{item.description}}
</td>
In order for this to work, I had to use an attribute selector for the app-item
component:
@Component({
selector: '[app-item]'
})
This works perfectly.
Now I want to improve it and add a second row in each app-item
. My problem is that the tr
tag lies in the app-list
component instead of the app-item
component. I thought that if I move it to the app-item
component, I could add another tr
and be able to show two rows per one item. So this is what I did. After that I used ng-container
to repeat the items in my app-list
, in order to avoid adding a wrapper tag around my two rows:
<ng-container *ngFor="let item of items" [item]="item" app-item></ng-container>
This solution did not work. I got the following error:
ERROR TypeError: el.setAttribute is not a function
at EmulatedEncapsulationDomRenderer2.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.DefaultDomRenderer2.setAttribute (platform-browser.js:1089)
at EmulatedEncapsulationDomRenderer2.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.EmulatedEncapsulationDomRenderer2.applyToHost (platform-browser.js:1157)
at DomRendererFactory2.push../node_modules/@angular/platform-browser/fesm5/platform-browser.js.DomRendererFactory2.createRenderer (platform-browser.js:1015)
Can you help me resolve this error or suggest another implementation?
EDIT: SOLUTION
The better version @Serhiy is suggesting
The table:
<table>
<app-item *ngFor="let item of items" [item]="item" remove-component-tag></app-item>
</table>
The directive:
import { Directive, ElementRef } from '@angular/core';
@Directive({
selector: '[remove-component-tag]'
})
export class RemoveComponentTagDirective {
constructor(private el: ElementRef) {
let element = el.nativeElement;
let children = el.nativeElement.childNodes;
setTimeout(()=>{
let reversedChildren = [];
children.forEach(child => {
reversedChildren.unshift(child);
});
reversedChildren.forEach(child => {
element.parentNode.insertBefore(child, element.nextSibling);
});
element.remove(element);
}, 0);
}
}
The timeout is necessary for some reason and works even with 0.