Completed
Last Updated: 16 Oct 2023 22:27 by Paul
Release 3.7.0 (09 Nov 2022)
Rob
Created on: 14 Jul 2021 12:49
Category: Scheduler
Type: Feature Request
16
OnEdit event should provide the resource values when creating an appointment in a grouped scheduler
I need some help with my question about how to know what grouping resource was clicked on. I'm using a custom editing screen that is triggered when the OnEdit event fires. I can't figure out how to get resource ID when the event fires. How do I get the resource group information on an event that fires with IsNew=true?
13 comments
Paul
Posted on: 16 Oct 2023 22:27

Hi Dimo

Thanks so much clarifying. I failed to understand that a new DTO was created by the scheduler - I was expecting to see something other than the appointment model to describe the slot, so this is awesome.

The only issue is that the edit event doesn't fire when resource grouping is turned on - it only works when there is no resource group turned on. I might have suggested that that was the intended behaviour, except for the that this thread is all about creating an appointment with grouping turned on.

I've created a forum question here:

How to enable Scheduler to create new Appointments when resourcing grouping is enabled in UI for Blazor | Telerik Forums


Could you please help me understand what I'm missing?

Thanks,

Paul

ADMIN
Dimo
Posted on: 16 Oct 2023 11:55

Hello Paul,

Yes, the described behavior is expected and this is how it works currently.

Also, if you use the Scheduler's OnEdit event, the resources will be provided as values in the Item property of the event argument. If we use the above example as a starting point, here is how to get them:

<TelerikScheduler OnEdit="@EditAppointment" />

@code {
    private void EditAppointment(SchedulerEditEventArgs args)
    {
        var item = (AppointmentDto)args.Item;
        var roomId = item.RoomId;
        Console.WriteLine($"Slot for room {roomId}");
    }
}

 

Regards,
Dimo
Progress Telerik

Stay tuned by visiting our public roadmap and feedback portal pages! Or perhaps, if you are new to our Telerik family, check out our getting started resources!
Paul
Posted on: 16 Oct 2023 08:47
This only helps if the user edits an existing appointment. What if there's resource grouping and the user double clicks an empty slot? Is there not an expectation from the user's perspective that they ought to be able to create a new appointment with the resource group already selected?
ADMIN
Dimo
Posted on: 11 Nov 2022 11:47

Hi Eric,

The resource values should be populated as properties in args.Item

Regards,
Dimo
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Foxy
Posted on: 11 Nov 2022 10:33

I installed the update - but cannot find the variable in 

    void EditAppointment(SchedulerEditEventArgs args)
    {
     }

 

ADMIN
Dimo
Posted on: 21 Oct 2022 07:01

Hello all,

This item will be included in the coming 3.7.0 release.

Regards,
Dimo
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Scott
Posted on: 14 Oct 2022 12:03
Hello, I see this item is completed. How do we go about getting the update?  Is there a hot-fix of some sort. Thanks.
Rob
Posted on: 05 Sep 2022 16:22

I hope this helps some people that are waiting for this feature.  This was critical for our business, so I had to figure out a workaround. I needed to go into the JavaScript to catch the events to handle the scheduler events.  In my case, I needed to catch the double click and right click(context menu) events on open time slots in the grid.  I started by adding some listeners to the Client\wwwroot\index.html scripts.  I have multiple pages that have schedules, so I centralized the script-- it can probably by added to the page with the scheduler if needed.

        function SetDotNetHelper(dotNetHelper) {
            window.dotNetHelper = dotNetHelper;
        }

 

       function attachContextMenu(parentClass) {
            window.setTimeout(function () {
                var schedulerSlotContainer = document.querySelector(parentClass + " .k-scheduler-body");
                if (schedulerSlotContainer) {
                    schedulerSlotContainer.addEventListener("contextmenu", e => {
                        if (e.target.className.indexOf("k-slot-cell") >= 0) {
                            // if time is empty, go to previous <div> row(s) to get it

                            var row = event.target.getAttribute("data-row-index")
                            var cell = event.target.getAttribute("data-cell-index")
                            var resource = event.target.getAttribute("data-resource-index")
                            window.dotNetHelper.invokeMethodAsync('OpenTimeSlotContext', row, cell, resource, e.clientX, e.clientY);
                        }
                        e.preventDefault();
                    });
                    schedulerSlotContainer.addEventListener("dblclick", e => {
                        if (e.target.className.indexOf("k-slot-cell") >= 0) {
                            // if time is empty, go to previous <div> row(s) to get it

                            var row = event.target.getAttribute("data-row-index")
                            var cell = event.target.getAttribute("data-cell-index")
                            var resource = event.target.getAttribute("data-resource-index")
                            window.dotNetHelper.invokeMethodAsync('OpenTimeSlotDoubleClick', row, cell, resource);
                        }
                        e.preventDefault();
                    });
                }
            });
        }

The next steps are in the page that contains the schedule.

Declare this as a variable for the the page.

        private DotNetObjectReference<EventCalendarBase> _dotNetHelper;

Add this code to OnAfterRenderAsync.

            if (!Loading) //Make sure intial loading is done.  Don't load javascript until schedule is displaying
            {
                await AttachContextMenu();
            }

The AttachContextMenu method.  (This process started with just the context menu and expanded to the double click later, so don't let the ContextMenu name discourage you.)  I had to reload the JavaScript when the view changed.  CurView is bound to the @bind-View of the scheduler.

        private async Task AttachContextMenu()
        {
            if (CurrView != _holdView)
            {
                await _js.InvokeVoidAsync("attachContextMenu", new[] { ".schedulerContainer " });
                _holdView = CurrView;
            }
        } 

You'll want a dispose as well.

        public void Dispose()
        {
            if (_dotNetHelper != null)
            {
                _dotNetHelper.Dispose();
            }
        }

Finally, here are the methods that are used when the context menu and double click methods are triggered.

        [JSInvokable]
        public void OpenTimeSlotDoubleClick(string Row, string Cell, string Resource)
        {
            GetContextInfo(Row, Cell, Resource);
            CreateNewEvent(SelectedSlotDateTime, SelectedSlotFacilityId); //Sets up and displays our custom edit form
            StateHasChanged();
        }

        [JSInvokable]
        public async Task OpenTimeSlotContext(string Row, string Cell, string Resource, int ClientX, int ClientY)
        {
            GetContextInfo(Row, Cell, Resource);
            await OpenContextMenuRef.ShowAsync(ClientX, ClientY); //Displays the context menu
        }

        public void GetContextInfo(string Row, string Cell, string Resource)
        {
            DateTime workingDate = SchedulerRef.Date;
            DateTime workingTime = SchedulerRef.Date;
            switch (SchedulerRef.View)
            {
                case SchedulerView.Day:
                    // date already set
                    SchedulerDayView dayView = (SchedulerDayView)SchedulerRef.SelectedView;
                    workingTime = CalculateSelectedTime(SchedulerRef.ShowWorkHours ? dayView.WorkDayStart : dayView.StartTime, dayView.SlotDuration, dayView.SlotDivisions, int.Parse(Row));
                    SelectedSlotDateTime = new DateTime(workingDate.Year, workingDate.Month, workingDate.Day, workingTime.Hour, workingTime.Minute, 0);
                    break;
                case SchedulerView.Week:
                    SchedulerWeekView vw = (SchedulerWeekView)SchedulerRef.SelectedView;

                    workingDate = CalculateWeekDate(int.Parse(Cell), SchedulerRef.Date);
                    workingTime = CalculateSelectedTime(SchedulerRef.ShowWorkHours ? vw.WorkDayStart : vw.StartTime, vw.SlotDuration, vw.SlotDivisions, int.Parse(Row));
                    SelectedSlotDateTime = new DateTime(workingDate.Year, workingDate.Month, workingDate.Day, workingTime.Hour, workingTime.Minute, 0);
                    break;
                case SchedulerView.MultiDay:
                    SchedulerMultiDayView multiDayView = (SchedulerMultiDayView)SchedulerRef.SelectedView;
                    workingDate = SchedulerRef.Date.AddDays(int.Parse(Cell));
                    workingTime = CalculateSelectedTime(SchedulerRef.ShowWorkHours ? multiDayView.WorkDayStart : multiDayView.StartTime, multiDayView.SlotDuration, multiDayView.SlotDivisions, int.Parse(Row));
                    SelectedSlotDateTime = new DateTime(workingDate.Year, workingDate.Month, workingDate.Day, workingTime.Hour, workingTime.Minute, 0);
                    break;
                case SchedulerView.Month:
                    break;
            }
            SelectedSlotFacilityId = long.Parse(FacilityResourceList[int.Parse(Resource)].Value);
        }

        private static DateTime CalculateWeekDate(int Cell, DateTime WeekDate)
        {
            if (WeekDate.DayOfWeek == DayOfWeek.Sunday)
            {
                return WeekDate;
            }
            for (int i = -1; i > -7; i--)
            {
                DateTime check = WeekDate.AddDays(i);
                if (check.DayOfWeek == DayOfWeek.Sunday)
                {
                    return check.AddDays(Cell);
                }
            }
            return WeekDate;
        }

        private static DateTime CalculateSelectedTime(DateTime StartTime, int SlotDuration, int SlotDivisions, int Row)
        {
            return StartTime.AddMinutes(Row * (SlotDuration / SlotDivisions));
        }

Hopefully someone can use this as a template to help move them down the road.

Rob

Support ATT
Posted on: 05 Sep 2022 06:06

Hi Telerik Team

We need here a solution, otherwise our customers will be unhappy. 

When do you think, we will get an update ? 

BR

ABDULLAH

CEO

Foxy
Posted on: 01 Sep 2022 23:32

same here,
in SchedulerEditEventArgs, Start, IsAllDay, ... is there, but NOT the Group ....


uuuppss...

ADMIN
Marin Bratanov
Posted on: 16 Jul 2022 13:15

Hi,

The best way to know when that happens is to click the Follow button to get emails for status updates. When a release is known we will update this page with its number and the status of the idea will be changed accordingly.

I have added your vote on your behalf (you can do that yourself for items you need by clicking the Vote button), as that is a metric our management uses when prioritizing tasks.

 

Regards,
Marin Bratanov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Support ATT
Posted on: 12 Jul 2022 09:38

Hi Telerik

Can you give us an Feedback, when the feature will be implemented ?

Thanks

 

Thomas
Posted on: 26 Jan 2022 22:11

Hi,

 

This is an important feature, cause if I want to have custom dialog to create appointment event in grouping resource then currently I can't do that!

 

Thanks,

Thomas