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:
As you can
see, using FastReport with knockout is quite simple.
Comments
Post a Comment