some.component.html
<table>
<tr *ngfor="let row in table">
<td *ngFor="let cell in row" (click)="onCellClick($event)">Cell Text</td>
</tr>
</table>
@Component({
selector: 'app-my-component',
template: '<div>My Component</div>',
})
export class MyComponent { }
@Component({
selector: 'app-some',
templateUrl: './some.component.html'
})
export class SomeComponent {
public table = [[1, 2, 3], [4, 5, 6]];
constructor(
private viewContainerRef: ViewContainerRef
) { }
onCellClick(event: MouseEvent): void {
const myComponent = this.viewContainerRef.createComponent(MyComponent);
}
}
This code adds MyComponent after </table>
. But I need MyComponent to be created inside of the clicked table cell (inside td
). How can I do it?
Note: This factory-less version only works if you have the same number of cells in every row (since we're using cellsPerRow to guess the index of the cell) :
Alright, first import everything we'll need :
import {
Component,
OnInit,
ViewContainerRef,
QueryList,
ViewChildren,
} from '@angular/core';
Add a ViewChildren decorator below your constructor to get all the cells elems :
@ViewChildren('cellElem', { read: ViewContainerRef })cellsElemsList: QueryList<ViewContainerRef>;
Add a cellsPerRow constant :
private cellPerRow = 3;
Then modify your onCellClick like so :
onCellClick = (rowIdx, colIdx) => {
const cellIdx = (rowIdx * this.cellPerRow) + colIdx;
this.cellsElemsList
.filter((el, idx) => idx === cellIdx)[0]
.createComponent(TestComponent);
};
Finally, change the HTML to pass the current cell's index to onCellClick() (and add the future component's container, #cellElem, inside your td elem) :
<div *ngFor="let row of rows; let rowIdx = index;">
<td *ngFor="let cell of row; let colIdx = index" (click)="onCellClick(rowIdx, colIdx)">
<div #cellElem></div>
Click me
</td>
</div>