2

I have a scheduler and a dropdown in a diary app. The scheduler is configured as such:

       $("#scheduler").kendoScheduler({
            date : Date.now(),
            workDayStart: new Date("2015/1/1 08:00 AM"),
            workDayEnd: new Date("2015/1/1 8:00 PM"),
            dateHeaderTemplate: kendo.template("<strong>#=kendo.toString(date, 'ddd dd/M')#</strong>"),
            majorTimeHeaderTemplate: kendo.template("<strong>#=kendo.toString(date, 'HH')#</strong><sup>00</sup>"),
            minorTimeHeaderTemplate: kendo.template("<strong>#=kendo.toString(date, 'HH')#</strong><sup>#=kendo.toString(date, 'mm')#</sup>"),
            selectable: true,
            messages: {
                ariaSlotLabel: "Selected from {0:g} to {0:g}",
                showWorkDay: "Show core work hours"
            },
            editable: {
                window: {
                    title: "Work Request Details",
                    width: "800px"
                },
                template: $("#customEditorTemplate").html()
            },
            edit: function (e) {
                //set the start end datetime
                if (e.event.isNew && e.event.id == -1) {
                    var startDtp = e.container.find("[name=start][data-role=datetimepicker]");
                    var endDtp = e.container.find("[name=end][data-role=datetimepicker]");
                    var setStartDate = e.event.start;
                    var setEndDate = e.event.end;
                    setStartDate.setHours(8);
                    setEndDate.setHours(-6); // by default the end date is midnight on the following day of the selected cell so we subtract 6h to get 18:00 on the selected date.
                    $(startDtp).data("kendoDateTimePicker").value(setStartDate); //set start date to the selected cell start date and time 08:00
                    $(endDtp).data("kendoDateTimePicker").value(setEndDate); //set enddate to the selected cell end date and time 18:00
                }

                var recurrenceEditor = e.container.find("[data-role=recurrenceeditor]").data("kendoRecurrenceEditor");
                //set start option value, used to define the week 'Repeat on' selected checkboxes
                recurrenceEditor.setOptions({
                start: new Date(e.event.start)
                });
            },
            eventTemplate: $("#eventTemplate").html(),
            height: 550,
            messages: {
                allDay: "Anytime"
            },
            views: [
                { type: "day", allDaySlot: true},
                { type: "week", eventHeight: 80 },
                { type: "timeline", eventHeight: 80 },
                { type: "timelineWeek", selected: true, majorTick: 1440, minorTickCount: 1, eventHeight: 80 },
                { type: "agenda" },
                { type: "month", eventHeight: 80 }
            ],
            timezone: "Etc/UTC",
            selectable: true,
            dataSource: {
                parameterMap: function parameterMap(data, type) {
                    console.log(type);
                    if (type === "read") {
                        //var reqFilter = wRequestFilter.value();
                        var reqFilter = 'ALL'
                        console.log(reqFilter);
                        if (reqFilter == "MY") {
                            data.filter = { logic: "and", filters: [{ field: "diary", operator: "eq", value: 'UIS' }, { field: "AssigneeID", operator: "eq", value: 1 }] };
                        } else if (reqFilter == "ALL") {
                            data.filter = { logic: "and", filters: [{ field: "diary", operator: "eq", value: 'UIS' }] };
                        } else {
                            data.filter = { logic: "and", filters: [{ field: "diary", operator: "eq", value: 'UIS' }, { field: "team", operator: "eq", value: reqFilter }] };
                        }

                    }
                    console.log(data);
                    return data;
                },
                type: "signalr",
                push: function (e) {
                    generateNotification(e.type, e.items[0].WRequestID, e.items[0].diary, e.items[0].team);
                },
                transport: {
                    signalr: {
                        hub: sHub,
                        promise: sHubStart,
                        server:   {
                            read: "read",
                            create: "create",
                            update: "update",
                            destroy: "destroy"
                        },
                        client: {
                            read: "read",
                            create: "create",
                            update: "update",
                            destroy: "destroy"
                        }
                    },
                },
                schema: {
                    model: {
                        id: "WRequestID",
                        fields: {
                            WRequestID: {
                                type: "number",
                                editable: false,
                                defaultValue: -1
                            },
                            start: {
                                from: "Start",
                                type: "date",
                                culture: "en-GB"
                            },
                            end :   {
                                from: "End",
                                type: "date",
                                culture: "en-GB" },
                            diary: {
                                from: "Diary",
                                type: "string",
                                defaultValue: "@AppShort"
                            },
                            team: {
                                from: "Team",
                                type: "string",
                                validation: { required: true }
                            },
                            title: {
                                from: "Title",
                                type: "string",
                                validation: { required: true }
                            },
                            workManager: {
                                from: "WorkManagerID",
                                type: "number",
                                validation: { required: true }
                            },
                            assignee: {
                                from: "AssigneeID",
                                type: "number",
                                validation: { required: true }
                            },
                            changeRef: {
                                from: "ChangeRef",
                                type: "string",
                                validation: { required: true }
                            },
                            description: {
                                from: "Description",
                                type: "string",
                                validation: { required: true }
                            },
                            impactedServers: {
                                from: "ImpactedServers",
                                type: "string",
                                validation: { required: true }
                            },
                            impactedServices: {
                                from: "ImpactedServices",
                                type: "string",
                                validation: { required: true }
                            },
                            isBAU: {
                                from: "IsBAU",
                                type: "boolean",
                                defaultValue: false
                            },
                            projectRef: {
                                from: "ProjectRef",
                                type: "string",
                                validation: { required: true }
                            },
                            notes: {
                                from: "Notes",
                                type: "string"
                            },
                            isOOH: {
                                from: "IsOOH",
                                type: "boolean",
                                defaultValue: false
                            },
                            isAllDay: {
                                from: "IsAllDay",
                                type: "boolean",
                                defaultValue: false
                            },
                            recurrenceRule: {
                                from: "RecurrenceRule",
                                type: "string"
                            },
                            recurrenceId: {
                                from: "RecurrenceID",
                                type: "number"
                            },
                            recurrenceException: {
                                from: "RecurrenceException",
                                type: "string"
                            },
                            startTimezone: {
                                from: "StartTimezone",
                                type: "string"
                            },
                            endTimezone: {
                                from: "EndTimezone",
                                type: "string"
                            },
                            requestStatus: {
                                from: "RequestStatus",
                                type: "number",
                                defaultValue: 0
                            }
                        }
                    },
                },
            }
        });

I am trying to use parameterMap to filter the data based on one or two bits of data.

  • If the dropdown value = ALL then the data is filtered by diary = @AppShort where @AppShort is derived from the web.config settings section.
  • If the dropdown value = MY then the data is further filtered to just display the current uses events
  • If the dropdown value is anything else then that means a team name is selected and so the data is filtered by diary and team.

My problem is that the data is not filtered at all and the parameterMap function is never triggered. Is this the best approach or is there another way of implementing filtering.

Any help appreciated.

UPDATE

As requested... this is my signalR hub code:

    Public Class WRequestHub
    Inherits Hub

    Private requestService As SchedulerRequestService

    Public Sub New()
        requestService = New SchedulerRequestService()
    End Sub

    Public Function Read() As IEnumerable(Of WRequestViewModel)
        Return requestService.GetAll()
    End Function

    Public Sub Update(request As WRequestViewModel)
        requestService.Update(request)
        Clients.Others.update(request)
    End Sub

    Public Sub Destroy(request As WRequestViewModel)
        requestService.Delete(request)
        Clients.Others.destroy(request)
    End Sub

    Public Function Create(request As WRequestViewModel) As WRequestViewModel

        requestService.Insert(request)
        Clients.Others.create(request)

        Return request

    End Function

    Public Sub LockRecord(id As Integer)
        Clients.Others.lockRecord(New With {
            Key .id = id
        })
    End Sub

    Public Sub UnlockRecord(id As Integer)
        Clients.Others.unlockRecord(New With {
            Key .id = id
        })
    End Sub

End Class

And this is my SchedulerRequestService class...

    Public Class SchedulerRequestService

    Public Overridable Function GetAll() As IQueryable(Of WRequestViewModel)

        Using de As New SupportDiaryEntities

            Dim rList As IQueryable(Of WRequestViewModel)

            rList = (From r In de.tWorkRequests
                     Select New WRequestViewModel() With {
                        .WRequestID = r.WRequestID,
                        .Start = r.Start,
                        .[End] = r.[End],
                        .Title = r.Title,
                        .Diary = r.Diary,
                        .Team = r.Team,
                        .WorkManagerID = r.WorkManagerID,
                        .AssigneeID = r.AssigneeID,
                        .ChangeRef = r.ChangeRef,
                        .Description = r.Description,
                        .ImpactedServers = r.ImpactedServers,
                        .ImpactedServices = r.ImpactedServices,
                        .IsBAU = r.IsBAU,
                        .ProjectRef = r.ProjectRef,
                        .Notes = r.Notes,
                        .IsOOH = r.IsOOH,
                        .IsAllDay = r.IsAllDay,
                        .RecurrenceRule = r.RecurrenceRule,
                        .RecurrenceID = r.RecurrenceID,
                        .RecurrenceException = r.RecurrenceException,
                        .StartTimezone = r.StartTimezone,
                        .EndTimezone = r.EndTimezone,
                        .RequestStatus = r.RequestStatus
                    }).ToList.AsQueryable()

            Return rList

        End Using

    End Function

        'OTHER FUNCTIONS (Insert, Update, Delete) Removed for brevity.
    End Class

UPDATE 2

With some help from Calinaadi and examples of filtering a SignalR datasource on a Kendo Grid I can see that I need to modify my read function to accept my filter(s). Unfortunately the examples used with the grid had .take, .skip, .sort, .filter and .aggregate as paramenters which I understand when you have a grid with paging and you want to take X records after skipping Y records.

This is a typical example from telerik demos...

    public DataSourceResult Read(MyDataSourceRequest request)
{
    return productService.Read().ToDataSourceResult(request.Take, request.Skip, request.Sort, request.Filter, request.Aggregates);
}

For a scheduler I would expect a read to fetch back all events with an end on or after the start of the current scheduler view and a start on or before the end of the current scheduler view. Probably sorted by start. Filtered by the field filters is necessary (these are the filters I've set). I can't see take, skip or aggregate have any concept in fetching event data.

My app function completely apart from the filtering. I have a VS solution I can share if necessary with database populated with dummy records.

Offering a bounty for any help.

Mych
  • 2,527
  • 4
  • 36
  • 65
  • Can you please add also the code where the filter is triggered? – calinaadi Jun 22 '16 at 15:10
  • @calinaadi I'm not sure I understand... The scheduler's would trigger a read when it is initialised I believe... The data source is bound via signalR. Do you mean the hub code? – Mych Jun 22 '16 at 20:06
  • @calinaadi I've added hub and the function called to read in data... You may have gathered I'm a bit out of my depth here... this project has snowballed from a basic calendar to one with many features. From what I read I thought that the filtering is done client side but I may be wrong... If it is server side how do I pass my filters with my read request? – Mych Jun 23 '16 at 12:39
  • Filtering is done on datasource you call it from client side using datasource.filter method an example to see it working: https://jsfiddle.net/valchev/MG89G/ – calinaadi Jun 24 '16 at 06:07
  • This example is using grid and the filters are static. I need dynamic as I have one field that will always be filtered on and another two that may or may not be filtered on. The values that are to be used to filter are also changeable. – Mych Jun 24 '16 at 06:25
  • Please see my answer i missed out that you are not declaring it in the right place and also you have a capital letter ParameterMap which is an error also – calinaadi Jun 24 '16 at 10:39

2 Answers2

3

You should change:

transport: {
                    signalr: {
                        hub: sHub,
                        promise: sHubStart,
                        ParameterMap: "parameterMap",

to:

transport: {
                       parameterMap: function parameterMap(data, type) {
                                                            alert(type);    
                                },
                        signalr: {
calinaadi
  • 1,466
  • 1
  • 13
  • 22
  • Calinaadi, I appreciate your help very much. I have updated the parameterMap section as instructed. I've also for the time being added static values just to test filtering rather than look up values from other element on page. I've added console.log commands to track various data. Unfortunately still no filtering. All data is displayed... no error and the logging produces no results... it is as if the parameterMap function is being disregarded. – Mych Jun 24 '16 at 11:15
  • Had a look at dojo example... but I can't see parameterMap working... alert(type) is not triggered. – Mych Jun 24 '16 at 12:08
  • I have even tried adding filter... http://dojo.telerik.com/@Mych/IMoGa/2 – Mych Jun 24 '16 at 12:17
  • I took a branch from the dojo you gave a link to... that had capital P and I didn't spot it. The alert now works but the filtering does not... see http://dojo.telerik.com/@Mych/IMoGa/3 which has a commented out filter. If you run the alert will pop up and the data is displayed. If you uncomment the data.filter line and run the alert pops up but no data is displayed... we should see all records where ProductName starts with T. – Mych Jun 24 '16 at 13:25
  • 1
    Filter will not work because you need to do something like parameterMap: function (options) { return JSON.stringify(options); } and on server side you will need to have an method that can handle such request.... just for ex public JsonResult Get(DataOptions options) where DataOptions is something like : public GridFilter Filter { get; set; } public int Skip { get; set; } public GridSort[] Sort { get; set; } public int Take { get; set; } – calinaadi Jun 24 '16 at 13:45
1

After many searches and much reading. I now have a working system. The scheduler required the parameter serverFiltering: true also the Read, Create, Update and Destroy functions has to be redone to accept the filter that was posted. If anyone would like a copy of the code which is a tad too much to post here I can let you have it.

Mych
  • 2,527
  • 4
  • 36
  • 65