How to use FastReport Open Source with the Knockout.js library


Knockout.js is a Javascript library for linking a data model with a view (html document). Any changes to the data automatically change the presentation and vice versa.
Although recently this library has been losing popularity against the background of Angular, React, Vue, nevertheless, a lot of sites are written in knockout. In general, it has quite a lot of fans.

How to create add knockout pattern for dotnet
First of all, make sure that you have Node.js installed - a software package for running JavaScript code on the server. Also, it includes the npm package manager, which allows you to install the necessary JavaScript libraries.
To create a one-page application with a server part based on ASP.Net Core MVC, we need a set of development tools .Net Core 2.0 or newer. You can install it separately by downloading from microsoft.com, or install Microsoft Visual Studio 2017. It already contains .Net Core 2.0 sdk.
The installed SDK can generate us a ready-made demo application using the template-based knockout libraries. Let's install the templates for single-page applications.
To do this, open the Windows command line in the folder where our new application will be located. Enter the following command to install the templates:
dotnet new — install Microsoft.AspNetCore.SpaTemplates::*
Next we will see the list of installed templates:
If among them you did not find the knockout, then try the installation again.
How to create a demo application
Now let’s create the application with the command:
dotnet new knockout -o KnockFROS
You will see the following warning:
Before running this project on the command line, you must restore NPM packages by running "npm install"
Well, go to the folder of the created application on the command line:
cd KnockFROS
And we execute the command:
npm install
After that, the package manager will analyze the package.json file and install the necessary packages.
Now we will add libraries
In the NuGet package manager, add two packages from the nuget.org repository — FastReport.OpenSource, FastReport.OpentSource.Web:
To use the FastReports libraries, add the line to the startup.cs file:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseFastReport();
        }
Do backend
In the wwwroot folder, add the App_Data folder, and in it add several report templates and a database:
We proceed to the creation of the server side. Since we already have a ready demo application, let's use the SampleDataController.cs controller:

using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using FastReport.Web;
using Microsoft.AspNetCore.Hosting;

namespace KnonkFROS.Controllers
{
    [Route("api/[controller]")]
    public class SampleDataController : Controller
    {

        private IHostingEnvironment _env;

        public SampleDataController(IHostingEnvironment env)
        {
            _env = env;
        }
        [HttpGet("[action]")]
        public IActionResult ShowReport(string name)
        {
            var webRoot = _env.WebRootPath;
            WebReport WebReport = new WebReport();
            WebReport.Width = "1000";
            WebReport.Height = "1000";
            WebReport.Report.Load(System.IO.Path.Combine(webRoot, (String.Format("App_Data/{0}.frx", name)))); // Load the report in the object WebReport
            System.Data.DataSet dataSet = new System.Data.DataSet(); // Create a data source
            dataSet.ReadXml(System.IO.Path.Combine(webRoot, "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();
        }
}
Now add a view for this method. Right click on the method signature. A view creation window will appear. Just click OK.
The ShowReport.chtml file will be generated in the Views-> SampleData folder. Change its content:
@await ViewBag.WebReport.Render()
Do frontend
Now we can go to the coding of the client part. Our application already contains several component pages. But we only need one - HomePage. In the ClientApp-> components-> home-page folder, open the home-page.html script file and replace its contents with:
<div>
    <div id="app">
        <select data-bind="options: reports, value: selectedReport"></select>
        <button data-bind="click: clicked">Show Report</button>
    </div>
    <div data-bind="if: show">
        <iframe id="report" height="1000" width="1000" data-bind="attr: {src: url}"></iframe>
    </div>
</div>
The component template is simple. First, a drop-down list of reports and a button are displayed. Then, depending on the value of the show variable, a frame is displayed with the report. This script is processed by the script, which is located in the same folder - home-page.ts:

import * as ko from 'knockout';

class HomePageViewModel {
    public show = ko.observable(false);
    public selectedReport = "Image";
    public url = ko.observable('');
    public reports = ko.observableArray(["Image", "Hierarchic List", "Matrix"]);

    public clicked() {
        if (this.selectedReport != null) {
            this.show(true);
            this.url("api/SampleData/ShowReport?name=" + this.selectedReport);
        }
    }
}

export default { viewModel: HomePageViewModel, template: require("./home-page.html") };
In this script, we declared several variables:
• show - flag indicating that the frame with the report should be displayed;
• selectedReport - contains the name of the report, which will be selected by default in the drop-down list;
• url - a link to the method in the controller that displays the report;
• reports - an array with the names of the reports for the drop-down list.
Also, there is a clicked () function that forms a link to the controller method, taking into account the report name selected in the drop-down list.
Remove unnecessary components in the app-root.ts file:
App-root.ts:
import * as ko from 'knockout';
import * as History from 'history';
import { Route, Router } from '../../router';
import navMenu from '../nav-menu/nav-menu';

// Declare the client-side routing configuration
const routes: Route[] = [
    { url: '',              params: { page: 'home-page' } },
    { url: 'report', params: { page: 'report' } }
];

class AppRootViewModel {
    public route: KnockoutObservable<Route>;
    public router: Router;

    constructor(params: { history: History.History, basename: string }) {
        // Activate the client-side router
        this.router = new Router(params.history, routes, params.basename);
        this.route = this.router.currentRoute;

        ko.components.register('nav-menu', navMenu);
        ko.components.register('home-page', require('bundle-loader?lazy!../home-page/home-page'));
    }
    public dispose() {
        this.router.dispose();

         // TODO: Need a better API for this
        Object.getOwnPropertyNames((<any>ko).components._allRegisteredComponents).forEach(componentName => {
            ko.components.unregister(componentName);
        });
    }
}

export default { viewModel: AppRootViewModel, template: require('./app-root.html') };
And also, remove the excess from the menu component template nav-menu.html:
<div class='main-nav'>
        <div class='navbar navbar-inverse'>
        <div class='navbar-header'>
            <button type='button' class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
                <span class='sr-only'>Toggle navigation</span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
                <span class='icon-bar'></span>
            </button>
            <a class='navbar-brand' href='/'>KnockFROS</a>
        </div>
        <div class='clearfix'></div>
        <div class='navbar-collapse collapse'>
            <ul class='nav navbar-nav'>
                <li>
                    <a data-bind='attr: { href: router.link("/") }, css: { active: route().page === "home-page" }'>
                        <span class='glyphicon glyphicon-home'></span> Home
                    </a>
                </li>
            </ul>
        </div>
    </div>
</div>

Our application is ready. Run it:
On the home page we see a drop-down list and the Show Report button.
The default report is Image. Click the Show Report button.
Choose another report. And click the Show Report button.
As you can see, using FastReport with knockout is quite simple.

Comments

Popular posts

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

FastReport Open Source - what is it and how to use it

FastReport Designer Community Edition