Angular 完整日历视图
Angular Full calendar View
我在我的项目中使用 angular 完整日历,我已经尝试过这个 https://mattlewis92.github.io/angular-calendar/#/kitchen-sink。
但在这方面,我遇到了一些错误。
这是我的 HTML 代码
<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)="closeOpenMonthViewDay()"
>
Previous
</div>
<div
class="btn btn-outline-secondary"
mwlCalendarToday
[(viewDate)]="viewDate"
>
Today
</div>
<div
class="btn btn-primary"
mwlCalendarNextView
[view]="view"
[(viewDate)]="viewDate"
(viewDateChange)="closeOpenMonthViewDay()"
>
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)="setView(CalendarView.Month)"
[class.active]="view === CalendarView.Month"
>
Month
</div>
<div
class="btn btn-primary"
(click)="setView(CalendarView.Week)"
[class.active]="view === CalendarView.Week"
>
Week
</div>
<div
class="btn btn-primary"
(click)="setView(CalendarView.Day)"
[class.active]="view === CalendarView.Day"
>
Day
</div>
</div>
</div>
</div>
<br />
<div [ngSwitch]="view">
<mwl-calendar-month-view
*ngSwitchCase="CalendarView.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="CalendarView.Week"
[viewDate]="viewDate"
[events]="events"
[refresh]="refresh"
(eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)"
>
</mwl-calendar-week-view>
<mwl-calendar-day-view
*ngSwitchCase="CalendarView.Day"
[viewDate]="viewDate"
[events]="events"
[refresh]="refresh"
(eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)"
>
</mwl-calendar-day-view>
</div>
<!-- Everything you see below is just for the demo, you don't need to include it in your app -->
<br /><br /><br />
<h3>
Edit events
<button class="btn btn-primary float-right" (click)="addEvent()">
Add new
</button>
<div class="clearfix"></div>
</h3>
<div class="table-responsive">
<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">
<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>
<input
class="form-control"
type="text"
mwlFlatpickr
[(ngModel)]="event.start"
(ngModelChange)="refresh.next()"
[altInput]="true"
[convertModelValue]="true"
[enableTime]="true"
dateFormat="Y-m-dTH:i"
altFormat="F j, Y H:i"
placeholder="Not set"
/>
</td>
<td>
<input
class="form-control"
type="text"
mwlFlatpickr
[(ngModel)]="event.end"
(ngModelChange)="refresh.next()"
[altInput]="true"
[convertModelValue]="true"
[enableTime]="true"
dateFormat="Y-m-dTH:i"
altFormat="F j, Y H:i"
placeholder="Not set"
/>
</td>
<td>
<button class="btn btn-danger" (click)="deleteEvent(event)">
Delete
</button>
</td>
</tr>
</tbody>
</table>
</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>
这是我的 component.ts 代码
import {
ChangeDetectionStrategy,
ViewChild,
TemplateRef,
} from '@angular/core';
import {
startOfDay,
endOfDay,
subDays,
addDays,
endOfMonth,
isSameDay,
isSameMonth,
addHours,
} from 'date-fns';
import { Subject } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {
CalendarEvent,
CalendarEventAction,
CalendarEventTimesChangedEvent,
CalendarView,
} from 'angular-calendar';
const colors: any = {
red: {
primary: '#ad2121',
secondary: '#FAE3E3',
},
blue: {
primary: '#1e90ff',
secondary: '#D1E8FF',
},
yellow: {
primary: '#e3bc08',
secondary: '#FDF1BA',
},
};
// declare let $:any;
// declare var jQuery: any;
@Component({
selector: 'app-attendance',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './attendance.component.html',
styleUrls: ['./attendance.component.scss']
})
export class AttendanceComponent implements OnInit {
@ViewChild('modalContent', { static: true })
modalContent!: TemplateRef<any>;
view: CalendarView = CalendarView.Month;
CalendarView = CalendarView;
viewDate: Date = new Date();
modalData!: {
action: string;
event: CalendarEvent;
};
actions: CalendarEventAction[] = [
{
label: '<i class="fas fa-fw fa-pencil-alt"></i>',
a11yLabel: 'Edit',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.handleEvent('Edited', event);
},
},
{
label: '<i class="fas fa-fw fa-trash-alt"></i>',
a11yLabel: 'Delete',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.events = this.events.filter((iEvent) => iEvent !== event);
this.handleEvent('Deleted', event);
},
},
];
refresh = new Subject<void>();
events: CalendarEvent[] = [
{
start: subDays(startOfDay(new Date()), 1),
end: addDays(new Date(), 1),
title: 'A 3 day event',
color: colors.red,
actions: this.actions,
allDay: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
{
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,
allDay: true,
},
{
start: addHours(startOfDay(new Date()), 2),
end: addHours(new Date(), 2),
title: 'A draggable and resizable event',
color: colors.yellow,
actions: this.actions,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
];
activeDayIsOpen: boolean = true;
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 {
this.events = this.events.map((iEvent) => {
if (iEvent === event) {
return {
...event,
start: newStart,
end: newEnd,
};
}
return iEvent;
});
this.handleEvent('Dropped or resized', event);
}
handleEvent(action: string, event: CalendarEvent): void {
this.modalData = { event, action };
this.modal.open(this.modalContent, { size: 'lg' });
}
addEvent(): void {
this.events = [
...this.events,
{
title: 'New event',
start: startOfDay(new Date()),
end: endOfDay(new Date()),
color: colors.red,
draggable: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
},
];
}
deleteEvent(eventToDelete: CalendarEvent) {
this.events = this.events.filter((event) => event !== eventToDelete);
}
setView(view: CalendarView) {
this.view = view;
}
closeOpenMonthViewDay() {
this.activeDayIsOpen = false;
}
这是我的 module.ts 文件
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { FormsModule } from '@angular/forms';
imports: [
BrowserModule,
CalendarModule.forRoot({
provide: DateAdapter,
useFactory: adapterFactory,
}),
FormsModule,
NgbModalModule
],
我收到这样的错误消息。
error TS2532: Object is possibly 'undefined'.
[(ngModel)]="event.color.primary"
Object is possibly 'undefined'.
[(ngModel)]="event.color.secondary"
Can't bind to 'altInput' since it isn't a known property of 'input'.
[altInput]="true"
Can't bind to 'enableTime' since it isn't a known property of 'input'. [enableTime]="true"
Can't bind to 'convertModelValue' since it isn't a known property of 'input'.
[convertModelValue]="true"
谁能帮我解决这些错误?
有关 event.color.primary
的错误应该是结果,您的颜色属于 any
类型并且没有定义特定类型。
尝试创建一个 IColors
接口并将 primary
和 secondary
条目定义为字符串。
关于 input
标签的错误是由于输入 HTML 元素到 angular 的未知属性造成的。
我在我的项目中使用 angular 完整日历,我已经尝试过这个 https://mattlewis92.github.io/angular-calendar/#/kitchen-sink。
但在这方面,我遇到了一些错误。
这是我的 HTML 代码
<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)="closeOpenMonthViewDay()"
>
Previous
</div>
<div
class="btn btn-outline-secondary"
mwlCalendarToday
[(viewDate)]="viewDate"
>
Today
</div>
<div
class="btn btn-primary"
mwlCalendarNextView
[view]="view"
[(viewDate)]="viewDate"
(viewDateChange)="closeOpenMonthViewDay()"
>
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)="setView(CalendarView.Month)"
[class.active]="view === CalendarView.Month"
>
Month
</div>
<div
class="btn btn-primary"
(click)="setView(CalendarView.Week)"
[class.active]="view === CalendarView.Week"
>
Week
</div>
<div
class="btn btn-primary"
(click)="setView(CalendarView.Day)"
[class.active]="view === CalendarView.Day"
>
Day
</div>
</div>
</div>
</div>
<br />
<div [ngSwitch]="view">
<mwl-calendar-month-view
*ngSwitchCase="CalendarView.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="CalendarView.Week"
[viewDate]="viewDate"
[events]="events"
[refresh]="refresh"
(eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)"
>
</mwl-calendar-week-view>
<mwl-calendar-day-view
*ngSwitchCase="CalendarView.Day"
[viewDate]="viewDate"
[events]="events"
[refresh]="refresh"
(eventClicked)="handleEvent('Clicked', $event.event)"
(eventTimesChanged)="eventTimesChanged($event)"
>
</mwl-calendar-day-view>
</div>
<!-- Everything you see below is just for the demo, you don't need to include it in your app -->
<br /><br /><br />
<h3>
Edit events
<button class="btn btn-primary float-right" (click)="addEvent()">
Add new
</button>
<div class="clearfix"></div>
</h3>
<div class="table-responsive">
<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">
<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>
<input
class="form-control"
type="text"
mwlFlatpickr
[(ngModel)]="event.start"
(ngModelChange)="refresh.next()"
[altInput]="true"
[convertModelValue]="true"
[enableTime]="true"
dateFormat="Y-m-dTH:i"
altFormat="F j, Y H:i"
placeholder="Not set"
/>
</td>
<td>
<input
class="form-control"
type="text"
mwlFlatpickr
[(ngModel)]="event.end"
(ngModelChange)="refresh.next()"
[altInput]="true"
[convertModelValue]="true"
[enableTime]="true"
dateFormat="Y-m-dTH:i"
altFormat="F j, Y H:i"
placeholder="Not set"
/>
</td>
<td>
<button class="btn btn-danger" (click)="deleteEvent(event)">
Delete
</button>
</td>
</tr>
</tbody>
</table>
</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>
这是我的 component.ts 代码
import {
ChangeDetectionStrategy,
ViewChild,
TemplateRef,
} from '@angular/core';
import {
startOfDay,
endOfDay,
subDays,
addDays,
endOfMonth,
isSameDay,
isSameMonth,
addHours,
} from 'date-fns';
import { Subject } from 'rxjs';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import {
CalendarEvent,
CalendarEventAction,
CalendarEventTimesChangedEvent,
CalendarView,
} from 'angular-calendar';
const colors: any = {
red: {
primary: '#ad2121',
secondary: '#FAE3E3',
},
blue: {
primary: '#1e90ff',
secondary: '#D1E8FF',
},
yellow: {
primary: '#e3bc08',
secondary: '#FDF1BA',
},
};
// declare let $:any;
// declare var jQuery: any;
@Component({
selector: 'app-attendance',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './attendance.component.html',
styleUrls: ['./attendance.component.scss']
})
export class AttendanceComponent implements OnInit {
@ViewChild('modalContent', { static: true })
modalContent!: TemplateRef<any>;
view: CalendarView = CalendarView.Month;
CalendarView = CalendarView;
viewDate: Date = new Date();
modalData!: {
action: string;
event: CalendarEvent;
};
actions: CalendarEventAction[] = [
{
label: '<i class="fas fa-fw fa-pencil-alt"></i>',
a11yLabel: 'Edit',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.handleEvent('Edited', event);
},
},
{
label: '<i class="fas fa-fw fa-trash-alt"></i>',
a11yLabel: 'Delete',
onClick: ({ event }: { event: CalendarEvent }): void => {
this.events = this.events.filter((iEvent) => iEvent !== event);
this.handleEvent('Deleted', event);
},
},
];
refresh = new Subject<void>();
events: CalendarEvent[] = [
{
start: subDays(startOfDay(new Date()), 1),
end: addDays(new Date(), 1),
title: 'A 3 day event',
color: colors.red,
actions: this.actions,
allDay: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
{
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,
allDay: true,
},
{
start: addHours(startOfDay(new Date()), 2),
end: addHours(new Date(), 2),
title: 'A draggable and resizable event',
color: colors.yellow,
actions: this.actions,
resizable: {
beforeStart: true,
afterEnd: true,
},
draggable: true,
},
];
activeDayIsOpen: boolean = true;
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 {
this.events = this.events.map((iEvent) => {
if (iEvent === event) {
return {
...event,
start: newStart,
end: newEnd,
};
}
return iEvent;
});
this.handleEvent('Dropped or resized', event);
}
handleEvent(action: string, event: CalendarEvent): void {
this.modalData = { event, action };
this.modal.open(this.modalContent, { size: 'lg' });
}
addEvent(): void {
this.events = [
...this.events,
{
title: 'New event',
start: startOfDay(new Date()),
end: endOfDay(new Date()),
color: colors.red,
draggable: true,
resizable: {
beforeStart: true,
afterEnd: true,
},
},
];
}
deleteEvent(eventToDelete: CalendarEvent) {
this.events = this.events.filter((event) => event !== eventToDelete);
}
setView(view: CalendarView) {
this.view = view;
}
closeOpenMonthViewDay() {
this.activeDayIsOpen = false;
}
这是我的 module.ts 文件
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
import { FormsModule } from '@angular/forms';
imports: [
BrowserModule,
CalendarModule.forRoot({
provide: DateAdapter,
useFactory: adapterFactory,
}),
FormsModule,
NgbModalModule
],
我收到这样的错误消息。
error TS2532: Object is possibly 'undefined'.
[(ngModel)]="event.color.primary"
Object is possibly 'undefined'.
[(ngModel)]="event.color.secondary"
Can't bind to 'altInput' since it isn't a known property of 'input'.
[altInput]="true"
Can't bind to 'enableTime' since it isn't a known property of 'input'. [enableTime]="true"
Can't bind to 'convertModelValue' since it isn't a known property of 'input'.
[convertModelValue]="true"
谁能帮我解决这些错误?
有关 event.color.primary
的错误应该是结果,您的颜色属于 any
类型并且没有定义特定类型。
尝试创建一个 IColors
接口并将 primary
和 secondary
条目定义为字符串。
关于 input
标签的错误是由于输入 HTML 元素到 angular 的未知属性造成的。