How can I position an element correctly on a table? The problem is that the table is dynamic, there can be n columns and n rows, then both width and height can change.
Result
My intention here is that according to a start and end time are the height of the element and the place of the column where it is located.
I leave an example of my code and attempts.
Stackblitz live code
Typescript.
hours = [
'8:00 AM',
'9:00 AM',
'10:00 AM',
'11:00 AM',
'12:00 PM',
'1:00 PM',
'2:00 PM',
'3:00 PM',
'4:00 PM',
'5:00 PM',
];
places = ['P1', 'P2', 'P3', 'P4', 'P5'];
events: any = [];
cellWidth = 0;
cellWidthHour = 0;
cellHeight = 0;
constructor() {}
ngAfterViewInit() {
this.getCellSize();
this.createEvent('10:00 AM', '12:00 PM', 'P3');
}
getCellSize() {
const cell = document.getElementsByClassName('cell')[0];
const cellWidthHour = document.getElementsByClassName('cell-hour')[0];
const cellRect = cell.getBoundingClientRect();
const cellRectHour = cellWidthHour.getBoundingClientRect();
this.cellWidth = cellRect.width;
this.cellHeight = cellRect.height;
this.cellWidthHour = cellRectHour.width;
console.log(this.cellWidth, this.cellHeight);
}
createEvent(startTime: string, endTime: string, location: string) {
const event: any = { startTime, endTime, location };
event.position = this.calculateEventPosition(startTime, endTime, location);
this.events.push(event);
}
calculateEventPosition(startTime: string, endTime: string, location: string) {
const start = this.hours.indexOf(startTime) + 1;
const end = this.hours.indexOf(endTime);
const place = this.places.indexOf(location);
const height = (end - start + 1) * this.cellHeight + 3;
const top = start * this.cellHeight - 6;
const left = place * this.cellWidth + this.cellWidthHour;
console.log(start, end, place);
console.log(height, top, left);
return {
height: height + 'px',
top: top + 'px',
left: left + 'px',
width: this.cellWidth + 'px',
};
}
HTML
<div class="calendar-container">
<table>
<tr>
<th></th>
<th *ngFor="let place of places">{{ place }}</th>
</tr>
<tr *ngFor="let hour of hours">
<td class="cell-hour">{{ hour }}</td>
<td class="cell" *ngFor="let place of places"></td>
</tr>
</table>
<div *ngFor="let event of events">
<div class="event" [ngStyle]="event.position">
<p>{{ event.location }}</p>
</div>
</div>
</div>
CSS
.calendar-container {
position: relative;
}
table {
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: center;
}
table td {
height: 25px;
}
.event {
position: absolute;
background-color: #f2f2f2;
padding: 12px;
border-radius: 4px;
}
I tried to generate these elements that are like cards in a dynamic way but I could not find the correct formula, sometimes it overflows or when I place it well just by readjusting the screen I lose the effect.