How to use the FastReport Open Source WebReport with ReactJS


The popular React library deservedly takes leading positions in web programming. Convenient and flexible tool for creating web applications. Today we will create an application on ReactJS in conjunction with ASP .Net Core. But this is not our main goal. And the main goal is to display FastReport reports using the FastReport.OpenSource library. This library is an open source report generator for the .Net Core platform from the FastReport company.

Create a project
To create an ASP project .Net Core + React we need Microsoft Visual Studio 2017, or .Net Core 2.0 SDK and higher. Also install the Node.js package. This is a toolkit for running javascript code on the server. Download the installation file from the developer’s site.
To create an ASP .Net Core project with a front-end to React, you can use a simple command from the command line:
dotnet new react -o FROSReact
Where FROSReact is the project name. As a result, we get a ready-made demonstration project, in which we simply make changes.

Backend
  • Add packages

To use the FastReport Open Source libraries in your project, you need to add them using the NuGet package manager. Open the package manager and find the library in the nuget.org repository: FastReport.OpenSource, FastReport.OpenSource.Web.
  • Startup

To use the added libraries, edit the startup.cs file:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseFastReport();
 }
  • Add reports and database to the project

We will need report files and a database for them. To do this, add the App_Data folder to the project root and drag the report template files and xml database for them:
  • Add a method to the controller

In our project there is already a SampleDataController controller. Add to it your method: [HttpGet("[action]")]
        public IActionResult DisplayReport(string name)
        {
            WebReport WebReport = new WebReport();
            WebReport.Width = "1000";
            WebReport.Height = "1000";
            WebReport.Report.Load(String.Format("App_Data/{0}.frx", name)); // Load the report into the WebReport object
            System.Data.DataSet dataSet = new System.Data.DataSet(); // Create a data source
            dataSet.ReadXml(@"App_Data/nwind.xml");  // Open the xml database
            WebReport.Report.RegisterData(dataSet, "NorthWind"); // Registering the data source in the report
            ViewBag.WebReport = WebReport; // Pass the report to View

            return View();
        }
• Add a view
In our project, there is no traditional for the mvc application folder View. Create it in the project root. And inside it is another SampleData folder, according to the name of the controller. In this folder we add a cshtml format view named DisplayReport, with the following content:

@await ViewBag.WebReport.Render()
The Render method will return the report in html format.
On this stage work with the backend is finished.
Frontend
Create a new Report.js component to display the report page in the ClientApp \ src \ components directory.
In it we need to implement:
• list of available reports;
• request for a report by name from the server;
• report display.
To display our new page, you need to make changes to some scripts.

NavMenu.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Navbar } from 'react-bootstrap';
import './NavMenu.css';

export class NavMenu extends Component {
  displayName = NavMenu.name

  render() {
    return (
      <Navbar inverse fixedTop fluid collapseOnSelect>
        <Navbar.Header>
          <Navbar.Brand>
            <Link to={'/'}>ReactFROS</Link>
          </Navbar.Brand>
          <Navbar.Toggle />
        </Navbar.Header>      
      </Navbar>
    );
  }
}

И App.js:

import React, { Component } from 'react';
import { Route } from 'react-router';
import { Layout } from './components/Layout';
import { Report } from './components/Report';

export default class App extends Component {
  displayName = App.name

  render() {
    return (
      <Layout>
        <Route exact path='/' component={Report} />
      </Layout>
    );
  }
}


Let's go back to the Report.js file. First, create a component class inherited from PureComponent.

import React, { PureComponent, Fragment } from 'react';

export class Report extends PureComponent {
constructor(props) {
        super(props);
}
render() {}
}
In the class constructor, we call the super class constructor (props) to make inheritance work.
To implement the list of reports, we need an array of objects with report names. Add it to the class constructor, and more specifically to the state:

this.state = {
                options: [
                {
                    value: 'Select report name …',
                },
                {
                    value: 'Matrix',
                },
                {
                    value: 'Master-Detail',
                },
                {
                    value: 'Text',
                },
            ]
        };
And now add the code to display the list:

 render() {
        const { options, value } = this.state;
        return (
                <div>
                    <Fragment>
                        <select onChange={this.handleChange} value={value}>
                            {options.map(item => (
                                <option key={item.value} value={item.value}>
                                    {item.value}
                                </option>
                            ))}
                        </select>
                    </Fragment>
                </div>
        );
    }
We use the Fragment component, which returns a list of elements, and nothing is added to the DOM. The select tag itself is filled with elements from an array using the map function. For the onChange event, you need to implement the handleChange handler. Add it to the Report class:

    handleChange = (event) => {
     this.setState({ value: event.target.value });
     this.name = event.target.value;
        };
Set the state for the value variable and set the report name, which we will pass as a parameter when calling the report generation method in the controller.
Now let's implement the report loading. Add a variable to render that will contain the html representation of the DisplayReport web method in the controller on the server.

render() {
        const { options, value } = this.state;

        let contents = this.name ? Report.getReport(this.name) : <div />;
       
        return (
            <div>
                    <div>
                        <Fragment>
                            <select onChange={this.handleChange} value={value}>
                                {options.map(item => (
                                    <option key={item.value} value={item.value}>
                                        {item.value}
                                    </option>
                                ))}
                            </select>
                        </Fragment>
                    </div>
                    {contents}
            </div>
        );
    }
Also, as you noticed, we added the output of the contents variable in the html code.
Implement the getReport report retrieval method. Add the following code to the Report class:

    static createMarkup(name) {
        return { __html: '<iframe height="1000" width="1000" src="api/SampleData/DisplayReport?name='+name+'" />' };
    }

    static getReport(name) {
        return (
            <div dangerouslySetInnerHTML={Report.createMarkup(name)} />
        )
    }
Here we had to implement two methods. The first one converts the textual representation of the tag frame into the html format, and the second one embeds the resulting code into the DOM. The dangerouslySetInnerHTML attribute replaces innerHTML.
That's all. This finishes the completion of the frontend. Let's run the application:
When loading the page, we will see only the drop-down list. Select from it the name of the report:
After which we will see the report:
Choose another report:
Summarizing, we can say that our goal has been achieved - an application to React, in which FastReport reports are displayed.

Comments

Popular posts

FastReport Designer Community Edition

How to use FastReport Open Source in ASP.NET Core Web API application