Good afternoon, I have a problem implementing the fullcalendar using angle 4, which is that it does not show me the dates, they only show me a list of numbers. This happens only with the calendar, the other components or functions, work well.
Module.ts
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
// import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { CalendarModule } from 'angular-calendar';
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { DemoUtilsModule } from './demo-utils/module';
// import { DemoUtilsModule } from '../demo-utils/module';
// import { DemoComponent } from './component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
CommonModule,
FormsModule,
NgbModalModule.forRoot(),
CalendarModule.forRoot(),
DemoUtilsModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Component.ts
import {
Component,
ChangeDetectionStrategy,
ViewChild,
TemplateRef
} from '@angular/core';
import {
startOfDay,
endOfDay,
subDays,
addDays,
endOfMonth,
isSameDay,
isSameMonth,
addHours
} from 'date-fns';
import { Subject } from 'rxjs/Subject';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {
CalendarEvent,
CalendarEventAction,
CalendarEventTimesChangedEvent
} from 'angular-calendar';
const colors: any = {
red: {
primary: '#ad2121',
secondary: '#FAE3E3'
},
blue: {
primary: '#1e90ff',
secondary: '#D1E8FF'
},
yellow: {
primary: '#e3bc08',
secondary: '#FDF1BA'
}
};
@Component({
selector: 'app-root',
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['./app.component.css'],
templateUrl: './app.component.html'
})
export class AppComponent {
@ViewChild('modalContent') modalContent: TemplateRef<any>;
view = 'month';
viewDate: Date = new Date();
modalData: {
action: string;
event: CalendarEvent;
};
actions: CalendarEventAction[] = [
{
label: '<i class="fa fa-fw fa-pencil"></i>',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.handleEvent('Edited', event);
}
},
{
label: '<i class="fa fa-fw fa-times"></i>',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.events = this.events.filter(iEvent => iEvent !== event);
this.handleEvent('Deleted', event);
}
}
];
refresh: Subject<any> = new Subject();
events: CalendarEvent[] = [
{
start: subDays(startOfDay(new Date()), 1),
end: addDays(new Date(), 1),
title: 'A 3 day event',
color: colors.red,
actions: this.actions
},
{
start: startOfDay(new Date()),
title: 'An event with no end date',
color: colors.yellow,
actions: this.actions
},
{
start: subDays(endOfMonth(new Date()), 3),
end: addDays(endOfMonth(new Date()), 3),
title: 'A long event that spans 2 months',
color: colors.blue
},
{
start: addHours(startOfDay(new Date()), 2),
end: new Date(),
title: 'A draggable and resizable event',
color: colors.yellow,
actions: this.actions,
resizable: {
beforeStart: true,
afterEnd: true
},
draggable: true
}
];
activeDayIsOpen = true;
constructor(private modal: NgbModal) {}
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
if (isSameMonth(date, this.viewDate)) {
if (
(isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
events.length === 0
) {
this.activeDayIsOpen = false;
} else {
this.activeDayIsOpen = true;
this.viewDate = date;
}
}
}
eventTimesChanged({
event,
newStart,
newEnd
}: CalendarEventTimesChangedEvent): void {
event.start = newStart;
event.end = newEnd;
this.handleEvent('Dropped or resized', event);
this.refresh.next();
}
handleEvent(action: string, event: CalendarEvent): void {
this.modalData = { event, action };
this.modal.open(this.modalContent, { size: 'lg' });
}
addEvent(): void {
this.events.push({
title: 'New event',
start: startOfDay(new Date()),
end: endOfDay(new Date()),
color: colors.red,
draggable: true,
resizable: {
beforeStart: true,
afterEnd: true
}
});
this.refresh.next();
}
}
Component.html
<h1>calendario</h1>
<div>
<ng-template #modalContent let-close="close">
<div class="modal-header">
<h5 class="modal-title">Event action occurred</h5>
<button type="button" class="close" (click)="close()">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div>
Action:
<pre>{{ modalData?.action }}</pre>
</div>
<div>
Event:
<pre>{{ modalData?.event | json }}</pre>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-secondary" (click)="close()">OK</button>
</div>
</ng-template>
<div class="row text-center">
<div class="col-md-4">
<div class="btn-group">
<div class="btn btn-primary" mwlCalendarPreviousView [view]="view" [(viewDate)]="viewDate" (viewDateChange)="activeDayIsOpen = false">
Previous
</div>
<div class="btn btn-outline-secondary" mwlCalendarToday [(viewDate)]="viewDate">
Today
</div>
<div class="btn btn-primary" mwlCalendarNextView [view]="view" [(viewDate)]="viewDate" (viewDateChange)="activeDayIsOpen = false">
Next
</div>
</div>
</div>
<div class="col-md-4">
<h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):'en' }}</h3>
</div>
<div class="col-md-4">
<div class="btn-group">
<div class="btn btn-primary" (click)="view = 'month'" [class.active]="view === 'month'">
Month
</div>
<div class="btn btn-primary" (click)="view = 'week'" [class.active]="view === 'week'">
Week
</div>
<div class="btn btn-primary" (click)="view = 'day'" [class.active]="view === 'day'">
Day
</div>
</div>
</div>
</div>
<br>
<div [ngSwitch]="view">
<mwl-calendar-month-view *ngSwitchCase="'month'" [viewDate]="viewDate" [events]="events" [refresh]="refresh" [activeDayIsOpen]="activeDayIsOpen"
(dayClicked)="dayClicked($event.day)" (eventClicked)="handleEvent('Clicked', $event.event)" (eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-month-view>
<mwl-calendar-week-view *ngSwitchCase="'week'" [viewDate]="viewDate" [events]="events" [refresh]="refresh" (eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-week-view>
<mwl-calendar-day-view *ngSwitchCase="'day'" [viewDate]="viewDate" [events]="events" [refresh]="refresh" (eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)">
</mwl-calendar-day-view>
</div>
<br>
<br>
<br>
<h3>
Edit events
<button class="btn btn-primary pull-right" (click)="addEvent()">
Add new
</button>
<div class="clearfix"></div>
</h3>
<table class="table table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Primary color</th>
<th>Secondary color</th>
<th>Starts at</th>
<th>Ends at</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let event of events; let index = index">
<td>
<input type="text" class="form-control" [(ngModel)]="event.title" (keyup)="refresh.next()">
</td>
<td>
<input type="color" [(ngModel)]="event.color.primary" (change)="refresh.next()">
</td>
<td>
<input type="color" [(ngModel)]="event.color.secondary" (change)="refresh.next()">
</td>
<td>
<mwl-demo-utils-date-time-picker [(ngModel)]="event.start" (ngModelChange)="refresh.next()" placeholder="Not set">
</mwl-demo-utils-date-time-picker>
</td>
<td>
<mwl-demo-utils-date-time-picker [(ngModel)]="event.end" (ngModelChange)="refresh.next()" placeholder="Not set">
</mwl-demo-utils-date-time-picker>
</td>
<td>
<button class="btn btn-danger" (click)="events.splice(index, 1); refresh.next()">
Delete
</button>
</td>
</tr>
</tbody>
</table>
</div>
I use these components:
calendar.header.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'mwl-demo-utils-calendar-header',
template: '
<div class="row text-center">
<div class="col-md-4">
<div class="btn-group">
<div
class="btn btn-primary"
mwlCalendarPreviousView
[view]="view"
[(viewDate)]="viewDate"
(viewDateChange)="viewDateChange.next(viewDate)">
Previous
</div>
<div
class="btn btn-outline-secondary"
mwlCalendarToday
[(viewDate)]="viewDate"
(viewDateChange)="viewDateChange.next(viewDate)">
Today
</div>
<div
class="btn btn-primary"
mwlCalendarNextView
[view]="view"
[(viewDate)]="viewDate"
(viewDateChange)="viewDateChange.next(viewDate)">
Next
</div>
</div>
</div>
<div class="col-md-4">
<h3>{{ viewDate | calendarDate:(view + 'ViewTitle'):locale }}</h3>
</div>
<div class="col-md-4">
<div class="btn-group">
<div
class="btn btn-primary"
(click)="viewChange.emit('month')"
[class.active]="view === 'month'">
Month
</div>
<div
class="btn btn-primary"
(click)="viewChange.emit('week')"
[class.active]="view === 'week'">
Week
</div>
<div
class="btn btn-primary"
(click)="viewChange.emit('day')"
[class.active]="view === 'day'">
Day
</div>
</div>
</div>
</div>
<br>
})
export class CalendarHeaderComponent {
@Input() view: string;
@Input() viewDate: Date;
@Input() locale: string = 'en';
@Output() viewChange: EventEmitter<string> = new EventEmitter();
@Output() viewDateChange: EventEmitter<Date> = new EventEmitter();
}
colors.ts
export const colors: any = {
red: {
primary: '#ad2121',
secondary: '#FAE3E3'
},
blue: {
primary: '#1e90ff',
secondary: '#D1E8FF'
},
yellow: {
primary: '#e3bc08',
secondary: '#FDF1BA'
}
};
date-time-picker.component.ts
import { ChangeDetectorRef, Component, forwardRef, Input } from '@angular/core';
import {
getSeconds,
getMinutes,
getHours,
getDate,
getMonth,
getYear,
setSeconds,
setMinutes,
setHours,
setDate,
setMonth,
setYear
} from 'date-fns';
import { NgbDateStruct, NgbTimeStruct } from '@ng-bootstrap/ng-bootstrap';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
export const DATE_TIME_PICKER_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateTimePickerComponent),
multi: true
};
@Component({
selector: 'mwl-demo-utils-date-time-picker',
template: '
<form class="form-inline">
<div class="form-group">
<div class="input-group">
<input
readonly
class="form-control"
[placeholder]="placeholder"
name="date"
[(ngModel)]="dateStruct"
(ngModelChange)="updateDate()"
ngbDatepicker
#datePicker="ngbDatepicker">
<div class="input-group-addon" (click)="datePicker.toggle()" >
<i class="fa fa-calendar"></i>
</div>
</div>
</div>
</form>
<ngb-timepicker
[(ngModel)]="timeStruct"
(ngModelChange)="updateTime()"
[meridian]="true">
</ngb-timepicker>
',
styles: [
'
.form-group {
width: 100%;
}
'
],
providers: [DATE_TIME_PICKER_CONTROL_VALUE_ACCESSOR]
})
export class DateTimePickerComponent implements ControlValueAccessor {
@Input() placeholder: string;
date: Date;
dateStruct: NgbDateStruct;
timeStruct: NgbTimeStruct;
datePicker: any;
private onChangeCallback: (date: Date) => void = () => {};
constructor(private cdr: ChangeDetectorRef) {}
writeValue(date: Date): void {
this.date = date;
this.dateStruct = {
day: getDate(date),
month: getMonth(date) + 1,
year: getYear(date)
};
this.timeStruct = {
second: getSeconds(date),
minute: getMinutes(date),
hour: getHours(date)
};
this.cdr.detectChanges();
}
registerOnChange(fn: any): void {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any): void {}
updateDate(): void {
const newDate: Date = setYear(
setMonth(
setDate(this.date, this.dateStruct.day),
this.dateStruct.month - 1
),
this.dateStruct.year
);
this.onChangeCallback(newDate);
}
updateTime(): void {
const newDate: Date = setHours(
setMinutes(
setSeconds(this.date, this.timeStruct.second),
this.timeStruct.minute
),
this.timeStruct.hour
);
this.onChangeCallback(newDate);
}
}
module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import {
NgbDatepickerModule,
NgbTimepickerModule
} from '@ng-bootstrap/ng-bootstrap';
import { CalendarModule } from 'angular-calendar';
import { CalendarHeaderComponent } from './calendar-header.component';
import { DateTimePickerComponent } from './date-time-picker.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
NgbDatepickerModule.forRoot(),
NgbTimepickerModule.forRoot(),
CalendarModule
],
declarations: [CalendarHeaderComponent, DateTimePickerComponent],
exports: [CalendarHeaderComponent, DateTimePickerComponent]
})
export class DemoUtilsModule {}