经过一周的工作,我设法得到了全日历版本 4在 blazor net5 中运行。
日历选项.cs
using System;
using System.Collections.Generic;
namespace SmartApp.Components
{
public class CalendarOptions
{
public string Id { get; set; }
public string DefaultView { get; set; } = CalendarView.ListWeek;
public DateTime DefaultDate { get; set; } = DateTime.Now;
public List<CalendarEvent> CalendarEvents { get; set; } = new List<CalendarEvent>();
}
public class CalendarEvent
{
public string Identifier { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime Start { get; set; }
public DateTime? End { get; set; }
public string Url { get; set; } = string.Empty;
public string SolidColor { get; set; }
public string DotColor { get; set; }
public string ClassName => $"{(string.IsNullOrEmpty(SolidColor) ? "" : $"fc-event-solid-{SolidColor}")} " +
$"{(string.IsNullOrEmpty(DotColor) ? "" : $"fc-event-{DotColor}")}";
public CalendarEventStatus Status { get; set; }
}
public class CalendarView
{
public static string DayGridMonth = "dayGridMonth";
public static string TimeGridWeek = "timeGridWeek";
public static string TimeGridDay = "timeGridDay";
public static string ListWeek = "listWeek";
}
public class CalendarEventSolidColor
{
public static string Primary = "primary";
public static string Warning = "warning";
public static string Error = "error";
public static string Success = "success";
public static string Info = "info";
}
public class CalendarEventDotColor
{
public static string Primary = "primary";
public static string Warning = "warning";
public static string Error = "error";
public static string Success = "success";
public static string Info = "info";
public static string Light = "light";
}
public enum CalendarEventStatus
{
Deleted = 0,
Active = 1,
Changed = 2
}
}
输入日历.razor这是一个可重复使用的组件
@namespace SmartApp.Components
@inject IJSRuntime JSRuntime
<div id="@Id"></div>
@code {
string _id;
[Parameter]
public string Id
{
get => _id ?? $"Calendar_{_uid}";
set => _id = value;
}
[Parameter]
public List<CalendarEvent> Events { get; set; }
[Parameter]
public string View { get; set; } = CalendarView.ListWeek;
[Parameter]
public EventCallback<List<CalendarEvent>> EventsChanged { get; set; }
readonly string _uid = Guid.NewGuid().ToString().ToLower().Replace("-", "");
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeVoidAsync("removeContent", $"#{Id}");
var options = new CalendarOptions
{
Id = Id,
DefaultView = View,
CalendarEvents = Events.Where(r => r.Status == CalendarEventStatus.Active).ToList()
};
await JSRuntime.InvokeVoidAsync("FullCalendarInterop.init", options, DotNetObjectReference.Create(this));
await base.OnAfterRenderAsync(firstRender);
}
[JSInvokable]
public async Task CalendarEventDeleted(string identifier)
{
var calendarEvent = Events.FirstOrDefault(x => x.Identifier == identifier);
if (calendarEvent != null)
calendarEvent.Status = CalendarEventStatus.Deleted;
await EventsChanged.InvokeAsync(Events);
}
[JSInvokable]
public Task SetDefaultView(string defaultView)
{
View = defaultView ?? CalendarView.ListWeek;
return Task.CompletedTask;
}
}
互操作js
FullCalendarInterop = (() => {
return {
//main function to initiate the module
init: function (options, dotNetReference) {
var calendarEl = document.getElementById(options.id);
var calendar = new window.FullCalendar.Calendar(calendarEl, {
plugins: ['interaction', 'dayGrid', 'timeGrid', 'list'],
isRTL: window.KTUtil.isRTL(),
header: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek'
},
height: 800,
contentHeight: 750,
aspectRatio: 3, // see: https://fullcalendar.io/docs/aspectRatio
views: {
dayGridMonth: { buttonText: 'month' },
timeGridWeek: { buttonText: 'week' },
timeGridDay: { buttonText: 'day' },
listWeek: { buttonText: 'list' }
},
defaultView: options.defaultView,
defaultDate: options.defaultDate,
editable: true,
eventLimit: true, // allow "more" link when too many events
navLinks: true,
events: options.calendarEvents,
eventRender: function (info) {
var event = $(info.event);
var element = $(info.el);
var view = $(info.view);
if (info.event.extendedProps && info.event.extendedProps.description) {
if (element.hasClass('fc-day-grid-event')) {
element.data('content', info.event.extendedProps.description);
element.data('placement', 'top');
window.KTApp.initPopover(element);
} else if (element.hasClass('fc-time-grid-event')) {
element.find('.fc-title').append('<div class="fc-description">' + info.event.extendedProps.description + '</div>');
} else if (element.find('.fc-list-item-title').lenght !== 0) {
element.find('.fc-list-item-title').append('<div class="fc-description">' + info.event.extendedProps.description + '</div>');
}
}
element.find(".fc-bg").css("pointer-events", "none");
element.find(".fc-list-item-title.fc-widget-content").prepend(
"<span style='position: absolute; right: 5px;'>" +
"<button class='btn btn-icon btn-xs btn-circle btn-light' " +
"style='height: 16px; width: 16px;' id='calendar_del_" + event.id + "'>" +
"<i class='icon-xs text-dark-50 flaticon2-cross'></i></button></span>");
element.find(".fc-content").append("<span style='position: absolute; top: 5px; right: 5px;'>" +
"<button class='btn btn-icon btn-xs btn-circle btn-light' " +
"style='height: 16px; width: 16px;' id='calendar_del_" + event.id + "'>" +
"<i class='icon-xs text-dark-50 flaticon2-cross'></i></button></span>");
element.find("#calendar_del_" + event.id).click(function () {
var eventId = event[0]._def.defId;
var eventIdentifier = event[0]._def.extendedProps.identifier;
//Remove popover
removeContent(".popover.fade.show.bs-popover-top");
//$(".popover.fade.show.bs-popover-top").remove();
dotNetReference.invokeMethodAsync('CalendarEventDeleted', eventIdentifier);
//$("#candidate_calendar").fullCalendar('removeEvents', eventId);
});
},
viewSkeletonRender: function(info) {
var view = $(info.view);
var defaultView = view[0].type !== null ? view[0].type : "";
dotNetReference.invokeMethodAsync('SetDefaultView', defaultView);
//alert(defaultView);
}
});
calendar.render();
}
};
})();
function removeContent(target) {
$(target).html("");
}
这就是我们在页面中实现它的方式。
页面剃刀
@inject IJSRuntime JS
<EditForm Model="@_calendarEvents">
<div class="card card-custom">
<div class="card-header">
<div class="card-title">
<h3 class="card-label">
Calendar
</h3>
</div>
<div class="card-toolbar">
<a href="#" class="btn btn-light-primary font-weight-bold">
<i class="ki ki-plus "></i> Add Event
</a>
</div>
</div>
<div class="card-body">
<InputCalendar Id="candidate_calendar" @bind-Events="_calendarEvents"></InputCalendar>
</div>
</div>
</EditForm>
@code {
private List<CalendarEvent> _calendarEvents;
protected override async Task OnInitializedAsync()
{
_calendarEvents =new List<CalendarEvent>
{
new CalendarEvent
{
Identifier = Guid.NewGuid().ToString(),
Title = "Breakfast",
Description = "Time to eat.",
Start = DateTime.Now.AddHours(6),
End = DateTime.Now.AddHours(7),
SolidColor = CalendarEventSolidColor.Primary,
DotColor = CalendarEventDotColor.Light,
Status = CalendarEventStatus.Active
},
new CalendarEvent
{
Identifier = Guid.NewGuid().ToString(),
Title = "Lunch",
Description = "Time to eat.",
Start = DateTime.Now.AddHours(10),
End = DateTime.Now.AddHours(11),
SolidColor = CalendarEventSolidColor.Warning,
DotColor = CalendarEventDotColor.Light,
Status = CalendarEventStatus.Active
}
};
await base.OnInitializedAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// If the calendar changes, we make an action here.
await base.OnAfterRenderAsync(firstRender);
}
}