When I use "<" or ">" to change date, it doesn't render the new month/day. I need to change view to refresh the render. I couldn't see where in my code, the problem occur.
Class and service outside of this razor component work correctly.
PlanningAgent.razor :
@using BlazorXLFacilities.Domain.Models
@using System.Drawing;
@using BlazorXLFacilities.Utils
@inject LoadingStatusService _loadingStatus
@inject IJSRuntime JS
@using Fluxor
@using BlazorXLFacilities.Store.DashBoard
@using BlazorXLFacilities.Pages.Components.Dashboard
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@inject IState<DashBoardState> _DashBoardState
@inject IDispatcher Dispatcher
<DashboardPanel @ref="Panel">
<DashboardPanelHeader Name="Planning des Agents">
<DashboardPanelToolbar>
<span class="button" @onclick="@Export">
<i class="fas fa-download"></i>
</span>
</DashboardPanelToolbar>
</DashboardPanelHeader>
<DashboardPanelBody>
<SfSchedule @ref="@Calendar"
TValue="AppointmentData"
@bind-SelectedDate="@SelectedDate"
Readonly="true"
StartHour="@StartHour"
EndHour="@EndHour"
MinDate="@StartDate"
MaxDate="@EndDate"
WorkDays="new int[] { 1, 2, 3, 4, 5, 6 }"
Width="100%">
<ScheduleEventSettings TValue="AppointmentData" DataSource="@visitesFormatted" ResourceColorField="CategoryColor"></ScheduleEventSettings>
<ScheduleEvents TValue="AppointmentData"/>
<ScheduleViews>
<ScheduleView Option="View.TimelineDay" DisplayName="Jour" >
<ScheduleViewTimeScale SlotCount="1" Interval="60"></ScheduleViewTimeScale>
</ScheduleView>
<ScheduleView Option="View.TimelineWeek" DisplayName="Semaine" >
<ScheduleViewTimeScale SlotCount="1" Interval="60"></ScheduleViewTimeScale>
</ScheduleView>
<ScheduleView Option="View.TimelineMonth" DisplayName="Mois" IsSelected="true">
<ScheduleViewTimeScale SlotCount="1" Interval="1440"></ScheduleViewTimeScale>
</ScheduleView>
</ScheduleViews>
<ScheduleGroup EnableCompactView="true" Resources="@GroupData"></ScheduleGroup>
<ScheduleResources>
<ScheduleResource TItem="User" TValue="int[]" DataSource="@Agents" Field="IdxUser" Title="Agent1" Name="Agents" TextField="PrenomNOM" IdField="IdxUser" AllowMultiple="true"></ScheduleResource>
</ScheduleResources>
<ScheduleTimeScale Enable="true" />
<ScheduleQuickInfoTemplates>
<HeaderTemplate>
@{
var data = context as AppointmentData;
SelectedDate = data.StartTime;
}
<div class="appointment@(data.CategoryColor)">
<div class="e-popup-header d-flex justify-content-end p-1 appointment@(data.CategoryColor)">
<button title="Fermer" class="e-control e-btn e-lib e-close e-flat e-round e-small e-icon-btn" @onclick="CloseQuickInfoPopup">
<span class="e-icons e-close-icon e-btn-icon"></span>
</button>
</div>
<div class="e-subject-wrap appointment@(data.CategoryColor)">
<div class="e-subject e-text-ellipsis">
@(data.Subject)
</div>
</div>
</div>
</HeaderTemplate>
</ScheduleQuickInfoTemplates>
</SfSchedule>
</DashboardPanelBody>
</DashboardPanel>
@code {
public string StartHour = "8:00";
public string EndHour = "21:00";
public DateTime StartDate => _DashBoardState.Value.StartDate.Value;
public DateTime EndDate => _DashBoardState.Value.EndDate.Value;
private List<VisiteSite> visites { get; set; }
private SfSchedule<AppointmentData> Calendar;
private DateTime SelectedDate = DateTime.Now;
public string[] GroupData = new string[] { "Agents" };
private List<AppointmentData> visitesFormatted { get; set; } = new();
private List<User> Agents { get; set; } = new();
private List<int> sitesIdx = new();
private string SchedulerId;
private bool refreshView = false;
protected override void OnInitialized()
{
base.OnInitialized();
SchedulerId = _loadingStatus.Register("Scheduler");
SelectedDate = EndDate.Date;
}
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
GetVisites();
_DashBoardState.StateChanged += UpdateDateRange;
_loadingStatus.ImLoaded(SchedulerId);
if (Panel != null) Panel.SetToFullScreen += UpdateAppointments;
}
else
{
if (refreshView)
{
refreshView = false;
if (Calendar != null) Calendar.ChangeDate(EndDate.Date);
SelectedDate = EndDate.Date;
StateHasChanged();
}
}
}
private void Export()
{
Calendar.ExportToExcel();
}
public void UpdateDateRange(object sender, DashBoardState state)
{
Calendar.RemoveResource(Agents.Select(ag => ag.IdxUser).ToList(), "Agents");
GetVisites();
refreshView = true;
Calendar.AddResource(Agents, "Agents", 1);
StateHasChanged();
}
public async void CloseQuickInfoPopup()
{
await Calendar.CloseQuickInfoPopup();
}
private void GetVisites()
{
visites = _DashBoardState.Value.VisitesLocal.GroupBy(v => v.IdxVisiteSite).Select(v => v.First().VisiteSite).Where(v => v != null).ToList();
sitesIdx = _DashBoardState.Value.VisitesLocal.GroupBy(v => v.IdxSite).Select(v => v.Key).ToList();
sitesIdx.Sort();
formatVisites();
_loadingStatus.ImLoaded(SchedulerId);
}
private string GetColor(int site)
{
var index = (double)sitesIdx.IndexOf(site);
if (index < 0) return "ffffff";
var length = (double)sitesIdx.Count();
var pos = (decimal)index / (decimal)length * 100;
var color = BlazorXLFacilities.Utils.Color.GetFromPercentage(pos);
return color.Name.Substring(2, 6);
}
private void formatVisites()
{
visitesFormatted.Clear();
Agents.Clear();
visitesFormatted.Add(new()
{
CssClass = "appointment-hidden",
Id = 0,
StartTime = EndDate.Date,
EndTime = EndDate.Date.AddHours(1)
});
visites.ForEach(v =>
{
var visiteLocal = _DashBoardState.Value.VisitesLocal.Where(vi => vi.IdxVisiteSite == v.IdxVisiteSite).First();
v.Site = visiteLocal?.Site;
if (!Agents.Any(a => a.IdxUser == v.IdxInspecteur))
{
Agents.Add(v.Inspecteur);
}
visitesFormatted.Add(new AppointmentData
{
Id = v.IdxVisiteSite,
IdxUser = v.IdxInspecteur,
Subject = "Prestation " + v.Site != null ? v.Site.Nom : "site inconnu",
Location = v.Site != null ? v.Site.AdresseComplete : null,
Description = v.Commentaire,
StartTime = v.Debut,
EndTime = v.Fin,
CategoryColor = GetColor(v.IdxSite),
CssClass = "appointment" + GetColor(v.IdxSite)
});
});
if (!Agents.Any()) Agents.Add(new()
{
Prenom = "Aucun Agent"
});
}
public class AppointmentData
{
public int Id { get; set; }
public int IdxUser { get; set; }
public string Subject { get; set; }
public string Location { get; set; }
public string Description { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public string CategoryColor { get; set; }
public string CssClass { get; set; }
}
public DashboardPanel Panel;
public void UpdateAppointments(object sender, System.EventArgs e)
{
Calendar.RefreshEventsAsync();
}
}
<style>
.e-excelexport::before {
content: '\e242';
}
.test {
display: flex;
width: 100%;
}
.test span {
height: 10px;
width: 10px;
display: block;
flex-grow: 1;
flex-basis: 0;
}
.appointment-hidden {
display: none !important;
}
.e-schedule .e-resource-left-td {
width: 200px !important;
}
</style>
@foreach (string c in visitesFormatted.GroupBy(v => v.CategoryColor).Select(c => c.Key).ToList())
{
var cl = ".appointment" + c;
<style>
.e-schedule .e-vertical-view .e-all-day-appointment-wrapper @cl,
.e-schedule .e-vertical-view .e-day-wrapper @cl,
.e-schedule @cl,
.e-schedule .e-month-view @cl,
.e-schedule .e-event-popup @cl {
background: #@c !important;
background-color: #@c !important;
border-color: #@c !important;
}
</style>
}
<style>
@foreach (int c in sitesIdx)
{
@(".test .c" + GetColor(c) + "{ background-color: #" + GetColor(c) + "; }")
}
</style>
Hi Geraud ,
Kindly try the issue replicating code and if the issue persists still share the below details to validate your reported issue and serve you better.
Regards,
Ruksar Moosa Sait
Hello,
I did some research on what was the problem exactly. To explain how it work, I have a principal page "DashBoard" who contain a SfTab with different TabItem, each TabItem contain a component "Dashboard" (created by last worker in my company). Each Dashboard contain a Row where differents components is put in place.
To Resume, I created a new Scheduler, put it in my principal page, it was working without any problem, after it I did put it in DashboardRow and the component couldn't directly update on date change.
This is the code of a DashboardRow :
@inject IJSRuntime JS
<CascadingValue Value="this">
<SfSplitter ID="@ID"
Width="100%"
CssClass="dashboard-row"
EnablePersistence="true"
SeparatorSize="4">
<SplitterEvents OnResizeStop="Resized" />
<SplitterPanes>
@ChildContent
</SplitterPanes>
</SfSplitter>
</CascadingValue>
@code {
[Parameter]
public RenderFragment ChildContent { get; set; }
[Parameter]
public string ID { get; set; }
public int PanelsCount => Panels.Count();
List<DashboardPanel> Panels = new();
public void AddPanel(DashboardPanel p)
{
Panels.Add(p);
}
public void RemovePanel(DashboardPanel p)
{
Panels.Remove(p);
}
private async void Resized()
{
await JS.InvokeVoidAsync("callWindowResize");
}
}
This is the code of my exemple Scheduler, TestScheduler :
@page "/Scheduler"
@using BlazorXLFacilities.Domain.Models
@using System.Drawing;
@using BlazorXLFacilities.Utils
@inject LoadingStatusService _loadingStatus
@using Fluxor
@using BlazorXLFacilities.Store.DashBoard
@using BlazorXLFacilities.Pages.Components.Dashboard
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@inject IState<DashBoardState> _DashBoardState
@inject IDispatcher Dispatcher
<DashboardPanel>
<DashboardPanelBody>
<SfSchedule @ref="Calendar"
TValue="AppointmentData"
@bind-SelectedDate="SelectedDate"
Readonly="true"
StartHour="@StartHour"
EndHour="@EndHour"
MinDate="@StartDate"
MaxDate="@EndDate"
WorkDays="new int[] { 1, 2, 3, 4, 5, 6 }"
Width="100%"
Height="auto">
<ScheduleEventSettings TValue="AppointmentData" DataSource="@visitesFormatted"></ScheduleEventSettings>
<ScheduleViews>
<ScheduleView Option="View.Day"></ScheduleView>
<ScheduleView Option="View.WorkWeek" DisplayName="Semaine"></ScheduleView>
<ScheduleView Option="View.Month" IsSelected="true"></ScheduleView>
</ScheduleViews>
<ScheduleQuickInfoTemplates>
<HeaderTemplate>
@{
var data = context as AppointmentData;
SelectedDate = data.StartTime;
}
<div class="appointment@(data.CategoryColor)">
<div class="e-popup-header d-flex justify-content-end p-1 appointment@(data.CategoryColor)">
<button title="Fermer" class="e-control e-btn e-lib e-close e-flat e-round e-small e-icon-btn" @onclick="CloseQuickInfoPopup">
<span class="e-icons e-close-icon e-btn-icon"></span>
</button>
</div>
<div class="e-subject-wrap appointment@(data.CategoryColor)">
<div class="e-subject e-text-ellipsis">
@(data.Subject)
</div>
</div>
</div>
</HeaderTemplate>
</ScheduleQuickInfoTemplates>
</SfSchedule>
</DashboardPanelBody>
</DashboardPanel>
<style>
.e-excelexport::before {
content: '\e242';
}
.appointment-hidden {
display: none !important;
}
</style>
@foreach (string c in visitesFormatted.GroupBy(v => v.CategoryColor).Select(c => c.Key).ToList())
{
var cl = ".appointment" + c;
<style>
.e-schedule .e-vertical-view .e-all-day-appointment-wrapper @cl,
.e-schedule .e-vertical-view .e-day-wrapper @cl,
.e-schedule .e-month-view @cl,
.e-schedule .e-event-popup @cl {
background-color: #@c;
border-color: #@c;
}
</style>
}
@code {
public SfSchedule<AppointmentData> Calendar;
private DateTime SelectedDate = DateTime.Now;
private string StartHour = "8:00";
private string EndHour = "21:00";
public DateTime StartDate => _DashBoardState.Value.StartDate.HasValue ? _DashBoardState.Value.StartDate.Value : new DateTime(2022, 01, 01);
public DateTime EndDate => _DashBoardState.Value.EndDate.HasValue ? _DashBoardState.Value.EndDate.Value : new DateTime(2022, 12, 31);
private List<VisiteSite> visites { get; set; }
public List<AppointmentData> visitesFormatted { get; set; } = new();
private List<int> sitesIdx = new();
private string SchedulerId;
private bool refreshView = false;
protected override void OnInitialized()
{
base.OnInitialized();
SchedulerId = _loadingStatus.Register("Scheduler");
SelectedDate = EndDate.Date;
}
protected override void OnAfterRender(bool firstRender)
{
base.OnAfterRender(firstRender);
if (firstRender)
{
GetVisites();
_DashBoardState.StateChanged += UpdateDateRange;
_loadingStatus.ImLoaded(SchedulerId);
}
else
{
if (refreshView)
{
refreshView = false;
if (Calendar != null) Calendar.ChangeDate(EndDate.Date);
SelectedDate = EndDate.Date;
StateHasChanged();
}
}
}
private void Export()
{
Calendar.ExportToExcel();
}
public void UpdateDateRange(object sender, DashBoardState state)
{
GetVisites();
refreshView = true;
StateHasChanged();
}
public async void CloseQuickInfoPopup()
{
await Calendar.CloseQuickInfoPopup();
}
private void GetVisites()
{
visites = _DashBoardState.Value.VisitesLocal.GroupBy(v => v.IdxVisiteSite).Select(v => v.First().VisiteSite).Where(v => v != null).ToList();
sitesIdx = _DashBoardState.Value.VisitesLocal.GroupBy(v => v.IdxSite).Select(v => v.Key).ToList();
sitesIdx.Sort();
formatVisites();
_loadingStatus.ImLoaded(SchedulerId);
}
private string GetColor(int site)
{
var index = (double)sitesIdx.IndexOf(site);
if (index < 0) return "ffffff";
var length = (double)sitesIdx.Count();
var pos = (decimal)index / (decimal)length * 100;
var color = BlazorXLFacilities.Utils.Color.GetFromPercentage(pos);
return color.Name.Substring(2, 6);
}
private void formatVisites()
{
visitesFormatted.Clear();
visitesFormatted.Add(new()
{
CssClass = "appointment-hidden",
Id = 0,
StartTime = EndDate.Date,
EndTime = EndDate.Date.AddHours(1)
});
visites.ForEach(v =>
{
v.Site = _DashBoardState.Value.VisitesLocal.Where(vi => vi.IdxVisiteSite == v.IdxVisiteSite).First()?.Site;
if (v.Site == null)
{
visitesFormatted.Add(new AppointmentData
{
Id = v.IdxVisiteSite,
Subject = "Prestation site inconnu",
Description = v.Commentaire,
StartTime = v.Debut,
EndTime = v.Fin,
CategoryColor = GetColor(v.IdxSite),
CssClass = "appointment" + GetColor(v.IdxSite)
});
}
else
{
visitesFormatted.Add(new AppointmentData
{
Id = v.IdxVisiteSite,
Subject = "Prestation " + v.Site.Nom,
Location = v.Site.AdresseComplete,
Description = v.Commentaire,
StartTime = v.Debut,
EndTime = v.Fin,
CategoryColor = GetColor(v.IdxSite),
CssClass = "appointment" + GetColor(v.IdxSite)
});
}
});
}
public class AppointmentData
{
public int Id { get; set; }
public string Subject { get; set; }
public string Location { get; set; }
public string Description { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public Nullable<bool> IsAllDay { get; set; }
public string CategoryColor { get; set; }
public string RecurrenceRule { get; set; }
public Nullable<int> RecurrenceID { get; set; }
public string RecurrenceException { get; set; }
public string StartTimezone { get; set; }
public string EndTimezone { get; set; }
public string CssClass { get; set; }
}
}
We have created a new ticket under your account to follow up with this query. We suggest you follow up with the ticket for further updates. Please log in using the below link.