это всего лишь идея. У вас есть такие события, как
events:any[]=[{
startDate:'2020-01-06',
endDate:'2020-01-08',
event:'Hello word'
}]
Когда вы отображаете календарь, добавьте «атрибуты данных» и поместите ссылку на переменную шаблона, чтобы мы могли получить ее, используя ViewChildren - get «row», потому что это будет важно, когда событие позвоните в две разные недели. Интересно, что вы даете в качестве атрибута день данных, который вы показываете. Для этого создайте такую функцию, как
getDate(day:any,row:number)
{
if (day.isSameMonth)
return this.currentMonth.getFullYear()+'-'+('0'+(this.currentMonth.getMonth()+1)).slice(-2)
+'-'+('0'+day.day).slice(-2)
if (row==0)
{
return this.currentMonth.getMonth()?
this.currentMonth.getFullYear()+'-'+
('0'+this.currentMonth.getMonth()).slice(-2)+'-'+
('0'+day.day).slice(-2):
(this.currentMonth.getFullYear()-1)+'-12-'+('0'+day.day).slice(-2)
}
return this.currentMonth.getMonth()!=11?
this.currentMonth.getFullYear()+'-'+
('0'+this.currentMonth.getMonth()+2).slice(-2)+'-'+
('0'+day.day).slice(-2):
(this.currentMonth.getFullYear()+1)+'-01-'+('0'+day.day).slice(-2)
}
<div #daysCell
[attr.data-day]="getDate(days,i)"
[attr.data-row]="i"
[ngClass] = "{'today-cell':days.isToday === true}">
{{days.day}}
</div>
. Отобразите события в элементе div как
<div *ngFor="let evento of events;let i=index">
<div #event [attr.data-event]="i" class="event">{{evento.event}}</div>
</div>
. Ну что ж, забавная часть. Мы получаем "ячейки" и "события" как
@ViewChildren('daysCell') cells:QueryList<ElementRef>
@ViewChildren('event') eventsCells:QueryList<ElementRef>
. И в функции renderEvent вы используете Renderer2, чтобы назначить вашим элементам левую верхнюю позицию
renderEvents(){
const cells=this.cells.map(x=>{
return {
pos:x.nativeElement.getBoundingClientRect(),
day:x.nativeElement.getAttribute('data-day'),
row:x.nativeElement.getAttribute('data-row'),
}
})
this.eventsCells.forEach((x:any,index:number)=>{
const cellStart=cells.find(c=>c.day==this.events[index].startDate)
const cellEnd=cells.find(c=>c.day==this.events[index].endDate)
this.render.setStyle(x.nativeElement,'top',(cellStart.pos.top+1)+'px')
this.render.setStyle(x.nativeElement,'left',(cellStart.pos.left+1)+'px')
this.render.setStyle(x.nativeElement,'width',
(cellEnd.pos.left-cellStart.pos.left+cellEnd.pos.width)+'px')
})
}
Хорошо, это всего лишь aprox. Вам нужно проверить, проходит ли событие через две недели, если оно показывается или нет ... и еще один корректирует (я надеюсь, что Миннор корректирует)
Вы можете увидеть в stackblitz
Обновление Если мы хотим разместить более одного события в дате, нам нужно добавить свойство ie к «событиям», например, мы можем назвать «row», так что «top» "становится как
this.render.setStyle(
x.nativeElement,
"top",
(this.events[index].row
? this.events[index].row *
(2 + x.nativeElement.getBoundingClientRect().height) +
cellStart.pos.top
: cellStart.pos.top + 1) + "px"
);
Теперь трудно понять, как дать значение" row ". Для этого нам нужно l oop поверх событий, сохранить в массиве дни, которые были заняты, и, если он занят, увеличить строку. слоеное. сделать функцию
getEventsRows() {
const datesOcupped: any[] = [];
this.events.forEach(x => {
x.row = 0;
const startDate = new Date(x.startDate).getTime();
const endDate = new Date(x.endDate).getTime();
for (let date = startDate;date <= endDate;date = date + 24 * 60 * 60 * 1000) {
const dateOcupped = datesOcupped.length?
datesOcupped.find(x => x.time == date): null;
if (!dateOcupped) {
datesOcupped.push({
time: date,
row: 0
});
} else dateOcupped.row++;
x.row = dateOcupped? dateOcupped.row > x.row?
dateOcupped.row: x.row: 0;
}
});
}