New to Telerik Reporting? Download free 30-day trial

Restrict report date parameters to a specific range

Environment

Product Progress Telerik Reporting
Report Viewer HTML5-based Report Viewers

Description

note Preliminary knowledge about implementing custom parameter editors is expected in order to fully understand and implement the approach showcased in this article - How to Create a Custom Parameter Editor

In some scenarios, one might want to set the Max date of a DateTime report parameter based on the selected date of another DateTime report parameter, essentially creating a range of dates that an end-user can pick from.

Let's imagine a report that has two DateTime Report Parameters with the following settings:

  • The first report parameter will have its Name set to the value DateRangeParam1 while its Text property can be equal to First date

  • The second report parameter will have its Name set to the value DateRangeParam2 while its Text property can be equal to Second date

In order to be able to use the code below without making changes to it, your report parameter should have their Names and Texts as clarified above

In order to add a range between those two DateTime report parameters, it is necessary to have access to the current value of the Start date report parameter. That is because the max date of the second report parameter will depend on the value of the first.

The only way to have access to the value of the first parameter every time that it changes is to create our own parameter editors as shown in the How to Create a Custom Parameter Editor article. We can re-use the kendo DatePIcker since it comes with the ability to specify a max date out of the box.

Solution

In the end, the code for the custom match function and the custom createEditor functions may look as follows:

$("#reportViewer1")
                .telerik_ReportViewer({
                    serviceUrl: "api/reports/",                  
                    reportSource: {
                        report: "ReportDateRange.trdp",
                    },
                    parameterEditors: [
                        {
                        match: customMatch,
                        createEditor: createCustomEditor
                       }
                    ],
                    //set the initial max date when the report viewer loads
                    renderingEnd: function (e, args) {
                        var firstDate = getDatePicker("First date").value();
                        var dateCopy = new Date(firstDate);
                        var newDate = new Date(dateCopy.setMonth(dateCopy.getMonth() + 3));

                        getDatePicker("Second date").max(newDate);
                    }
                });
        }).data("telerik_ReportViewer");

        function customMatch(parameter) {
            // Setting the name exactly to DateRangeParam1(or another name that you prefer) is important in order to do this check
            return parameter.type === "System.DateTime" && parameter.name === "DateRangeParam1" ;
        }

        function createCustomEditor(placeholder, options) {

            $(placeholder).html('<input type="datetime"/>');
            var datePicker = $(placeholder),
                parameter,
                valueChangedCallback = options.parameterChanged;

            function onChange(e) {
                var datePickerEndDate = getDatePicker("Second date");

                var dtv = this.value();
                var dateCopy = new Date(dtv);
                // for this example, we add a range of 3 months from the first date
                var newMaxDate = new Date(dateCopy.setMonth(dateCopy.getMonth() + 3));

                datePickerEndDate.max(newMaxDate);

                //timezone needs adjustments, see the function code down below
                valueChangedCallback(parameter, adjustTimezone(dtv));
            }

            return {
                beginEdit: function (param) {
                    parameter = param;

                    var date = null;
                    try {
                        if (param.value) {
                            date = param.value;
                            date = unadjustTimezone(date);
                        }
                    } catch (e) {
                        date = null;
                    }

                    $(datePicker).find("input").kendoDatePicker({
                        change: onChange,
                        value: date
                    });

                    datePicker = $(datePicker).find("input").data("kendoDatePicker");
                }
            };
        }

        function adjustTimezone(date) {
            return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
        }

        function unadjustTimezone(date) {
            return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
        }

        function getDatePicker(dateText) {
            return $(`.trv-parameter-header div[title='${dateText}']`)
                .parent().parent().find(".trv-parameter-value input").data("kendoDatePicker");
        }

Notes

Looking at the code in the solution, one might wonder why do we need to both set the max of the second DatePicker in both the change event of the start date widget and in the renderingEnd event of the report viewer.

The reason is that this article's goal is to make sure it works in preferably all scenarios. If both report parameters have their AutoRefresh property set to True, when the start date is updated, the report viewer will re-render and thus renderingEnd will be fired and the max date of the second date parameter will update. In such a scenario, the custom parameter editor is most likely unnecessary.

However, if AutoRefresh is False, then the only way to know when the first date widget will update is if we have access to its change event, thus in this scenario it is necessary to also have the custom parameter editor functions.

What is certain is that in any case, the renderingEnd event function is necessary because in both scenarios, we need to set the initial max date of the second widget.

See Also

In this article