How to interact with ReportViewer during the initial load of a razor page in Blazor

3 Answers 262 Views
Report Viewer - Blazor
Daniel
Top achievements
Rank 1
Iron
Iron
Iron
Daniel asked on 25 Nov 2021, 06:28 PM

I have a razor page in my Blazor server app with a report viewer control on it (named AllowanceDetailViewer in the code below). I gather the desired parameter values for this report from the user on page 1 and then launch page 2 and pass it those values. On page 2 I want the report to display using the passed values when the page loads.

The issue is where do I put the call to the Refresh() function on page 2? If I put a call in OnInitializedAsync() I get an error that the AllowanceDetailViewer object is null (so it hasn't loaded yet). If I put a call in OnAfterRenderAsync() I get an internal error from the viewer control. Is there a page event I can use where the report viewer is fully loaded and ready for use?

Note: if I add a button to the page and call the Refresh() function from the button click it works fine. That tells me the code in the Refresh() function is working. What I want is to call that code during the initial page load so it happens automatically without the user needing to click on something first.

        

<ReportViewer @ref="AllowanceDetailViewer" ViewerId="rv1" ServiceUrl="api/reports" ReportSource="@(new ReportSourceOptions { Report = "BlankReport.trdp" })" ScaleMode="@(ScaleMode.Specific)" Scale="1.0" ViewMode="ViewMode.Interactive" ClientEvents= "@(new ClientEventsOptions() {Ready = "ReportReady"})" />

 


        async Task Refresh()
        {
            rso.Report = "AllowanceDetail.trdp";
            await AllowanceDetailViewer.SetReportSourceAsync(rso);

            rso = await AllowanceDetailViewer.GetReportSourceAsync();

	    //code here setting a bunch of parameters, this is just a stub
            rso.Parameters["parameter1"] = "new parameter value";

            await AllowanceDetailViewer.SetReportSourceAsync(rso);
        }


3 Answers, 1 is accepted

Sort by
0
Accepted
Daniel
Top achievements
Rank 1
Iron
Iron
Iron
answered on 08 Dec 2021, 01:55 PM
I was able to get it to work using the OnParametersSetAsync method instead of SetParametersAsync. In SetParametersAsync all the parameters are blank but I need the value for one of them so I can lookup the others. With OnParametersSetAsync I was able to do that.
0
Dimitar
Telerik team
answered on 30 Nov 2021, 03:36 PM

Hello Daniel,

Thank you for the provided information!

The report viewer component ref is indeed null on the first render, that is why you cannot use the mentioned methods. Generally, I would recommend creating Parameters in your blazor components in which you would then pass to the report viewer's ReportSource object, please see Parameters In Blazor Components for more information. This way you will not need to get and set the report source multiple times because these are operations that cause the report viewer to re-render and in big reports, that may be quite costly.

After you have introduced such component parameters, you may then, for example, make additional edits if needed when the parameters have been est in the (OnParametersSet{Async}) lifecycle event or when setting the parameters in (SetParametersAsync).

Besides the parameters approach, you also have the option of using the report viewer's ready() event, as it seems that you have already attempted to use it (judging by the code snippet). Binding to the blazor report viewer event component is a little complicated and for that reason, I suggest having a look at the Event Binding article. Also, please check out the following example for updating the viewer report source:

In _Host.cshtml

    <script>
        window.trvEventHandlers = {
            ready: function () {
                this.reportSource({report: "Invoice.trdp"});               
            }
        }
    </script>

Then on the component page:

<ReportViewer @ref="reportViewer1"
            ....
              ClientEvents="@(new ClientEventsOptions() {
                                  Ready = "trvEventHandlers.ready"
                              })" />

Please test the proposed solutions and let me know if you have any other questions or need further assistance.

Regards,
Dimitar
Progress Telerik

Brand new Telerik Reporting course in Virtual Classroom - the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products. Check it out at https://learn.telerik.com/.
0
Daniel
Top achievements
Rank 1
Iron
Iron
Iron
answered on 02 Dec 2021, 01:15 PM

Hi,

Thank you for looking at this. Unfortunately I don't think this will work.

Currently I am passing parameters to the blazor page but as a single database ID that let's me lookup the full list of parameters. There's two reasons for this, (1) some of the parameter values are XML strings and possibly too long to include on the URL, and (2) it avoids exposing the parameter values to direct user manipulation.

The scheme I have works just fine when a button is clicked after the form is loaded. I just want the same thing to happen somewhere during/just after the form is loaded so the user doesn't have to click on something first. I tried the events you suggested (OnParametersSetAsync and SetParametersAsync) but those also give errors that the report object reference is null.

I did look into the ready() function but I'm not sure I can work with that. I don't know how to trigger the parameter value assignment from there. Also, this report happens to be the first one in this project but it won't be the last, there's going to be 50 more in this same app. I'm not sure a single method in _host.cshtml is going to suffice for all of them.

So there's no event that exists on a page to say that loading has finished and the page is ready?

Dimitar
Telerik team
commented on 07 Dec 2021, 08:58 AM

The blazor report viewer is not a native blazor component but rather a wrapper of the HTML5 viewer. It uses JS Interop to load the report viewer after the component has been initialized. Currently, we do not throw an event for when everything has been completely loaded. I suggest making a feature request on our feedback portal regarding throwing such an event.

Current workarounds that you may use are the parameters lifecycle events but the idea is not to use the report viewer object to call the setReportSource method, instead, you can have component parameters that are passed as values to the report parameters of the report and in the (SetParametersAsync) event, for example, you may look up the values for the parameters and set them. For example, with the Invoice.trdp report:

<ReportViewer @ref="reportViewer1"
              ViewerId="rv1"
              ServiceUrl="/api/reports"
              ReportSource="@(new ReportSourceOptions
                              {
                                  Report = "Invoice.trdp",
                                  Parameters = new Dictionary<string, object>{
                                     { "OrderNumber", @OrderNumber ?? "SO51081" } 
                                  }
                              })"
              Parameters="@(new ParametersOptions { Editors = new EditorsOptions { MultiSelect = EditorType.ComboBox, SingleSelect = EditorType.ComboBox } })"
              ScaleMode="@(ScaleMode.Specific)"
              Scale="1.0"
              ClientEvents="@(new ClientEventsOptions() {
                                  ExportBegin = "trvEventHandlers.exportBegin",
                                  ExportEnd = "trvEventHandlers.exportEnd",
                                  Ready = "trvEventHandlers.ready"
                              })" />

@code {
    ReportViewer reportViewer1;

    [Parameter]
    public string OrderNumber{ get; set; }

        public override Task SetParametersAsync(ParameterView parameters)
    {
        this.OrderNumber = "SO51088";
        return base.SetParametersAsync(parameters);
    }
}

Tags
Report Viewer - Blazor
Asked by
Daniel
Top achievements
Rank 1
Iron
Iron
Iron
Answers by
Daniel
Top achievements
Rank 1
Iron
Iron
Iron
Dimitar
Telerik team
Share this question
or