3

I'm working in an implementation using SignalR and the Kendo Scheduler. When a new task is created (for exemple), the SchedulerDataSource transport send the connection hub id to the server as an additional parameter:

transport: {
    read: { url: global.web_path + 'Home/Tasks' },
    update: { url: global.web_path + 'Home/UpdateTask', type: 'PUT', contentType: 'application/json' },
    create: { url: global.web_path + 'Home/CreateTask', type: 'POST', contentType: 'application/json' },
    destroy: { url: global.web_path + 'Home/DeleteTask', type: 'DELETE', contentType: 'application/json' },
    parameterMap: function (options, operation) {
        if (operation == "destroy" && options.models) {
            return JSON.stringify({ taskId: options.models[0].Id, callerId: $.connection.hub.id });
        }
        if (operation !== "read" && options.models) {
            return JSON.stringify({ tasks: options.models, callerId: $.connection.hub.id });
        }
    }
},

The server do whatever it has to do, and send a notification to every other user, except de caller:

[HttpPost]
public JsonResult CreateTask(List<ScheduledEvent> tasks, string callerId)
{
   ...create task and other stuff

   //broadcast the newly created object to everyone except caller
   var hubContext =     GlobalHost.ConnectionManager.GetHubContext<Notebooks.Hubs.SchedulerHub>();
   hubContext.Clients.AllExcept(callerId).UpdateSchedule(task);

   //return the object to caller
   return Json(task);
}

Once the other clients receive a new task from the hub, it is added to the SchedulerDataSource:

hub.client.updateSchedule = function (scheduledEvent) {
   schedulerDataSource.add(scheduledEvent);
}

Everything seems to work fine, and it really took me some time to realize this behavior: if a client have the scheduler window open, this window is closed once the schedulerDataSource is updated. This is expected or am I doing something wrong?

Ahmad Ibrahim
  • 1,915
  • 2
  • 15
  • 32
Eduardo
  • 283
  • 2
  • 9

2 Answers2

0

Edit: I just realized how old this question is, so you have probably moved on to other things by now, or the pushCreate method may not have existed back then.

I think this may be how it works, but it seems like it should be able to add those events behind the scenes without having to close the edit window. Have you tried the pushCreate method? If that doesn't work, since the add automatically closes the edit dialog, maybe when the events come in, if the dialog is open, you could store the new events, then add them when the user closes the edit dialog.

Michael
  • 498
  • 3
  • 13
0

My answer is now even older ;) but I faced this very same issue today.

First, I'm quite sure this is indeed the expected behavior. You can see in the kendo sources the call of the close editor window method in the transport update and create methods of the scheduler.

Below is what I've done to bypass the issue . The idea is as simple as to prevent the edit window to close when an appointment modification comes from another hub client.

Server-side : modify the hub methods (example with update method)

    public MyAppointmentViewModel Update(MyAppointmentViewModel appointment)
    {
        if (!appointmentService.Update(appointment))
             throw new InvalidOperationException("Something went wrong");
        else
        {
             Clients.Others.PrepareBeforeAddOrUpdateSignal(appointment.Id);
             Clients.Others.Update(appointment);
             return appointment;

        }
    }

Here you see we inform every other clients (through PrepareBeforeAddOrUpdate) we're about to update an appintment.

Client-side now (in index.cshtml for instance)

schedulerHub.client.prepareBeforeAddOrUpdateSignal = function(id){ lastModifiedRdvId = id; };
schedulerHub.client.create = function(appointment){ lastModifiedRdvId = 0; }; /* reset the variable for next time */
schedulerHub.client.update = function(appointment){ lastModifiedRdvId = 0; }; /* reset the variable for next time */

function SchedulerEditor()
{
    return $(".k-scheduler-edit-form").data("kendoWindow");
}

var eventBeforeChanges = null;
var lastModifiedRdvId = 0;

function onEditorClose(e) {
    if (eventBeforeChanges != null) {
        if (lastModifiedRdvId > 0 && eventBeforeChanges.Id != lastModifiedRdvId)
            e.preventDefault();
    else {
        var editWin = SchedulerEditor(); /* unbind this callback and use default behavior again */
        editWin.unbind('close', onEditorClose);
    }
}}
function onEditRdv(e) {    
    var editWin = SchedulerEditor();
    if (editWin != null) /*Bind the close event */
        editWin.unbind('close', onEditorClose).bind('close', onEditorClose);

     eventBeforeChanges = e.event;

     /* continue onEditRdv */
}

you see here the close event is prevented when the appointment id is not the appointment id beeing updated by the current client.

And fortunately, preventing the close event prevents the annoying behavior of having a sort of ghost appointment after one has been changed by another hub client.

I'm sorry if I'm not clear or if the code isn't clear enough. I can provide more information if necessary.

Bye