FusionCharts is a JavaScript charting library providing 100+ charts and 2,000+ maps for your web and mobile applications. All the visualizations are interactive and animated, which are rendered using webview. This plugin provides Flutter interface which integrates with FC Core JavaScript library using webview. This package also contains FusionTime (timeseries charts), FusionWidgets (gauges, real-time charts), PowerCharts (statistical and advanced charts), and FusionMaps (choropleth geo maps).
- Official Website: https://www.fusioncharts.com/
- Documentation: https://www.fusioncharts.com/dev/
- Licensing: Legal Terms & Customer Agreements
- Support: https://www.fusioncharts.com/contact-support
Every year, new frameworks emerge in the JavaScript ecosystem. FusionCharts, being a JavaScript library, needs to keep up with these developments to encourage wider adoption. There has been observed an increase in the demand for integration, especially among Blazor developers. As a result, this project focuses on creating an integration specifically tailored for Blazor developer community
- Github Repo: https://github.com/fusioncharts/blazor-fusioncharts
- Documentation:
- Support:
- FusionCharts
- Official Website: https://www.fusioncharts.com/
- Official NPM Package: https://www.npmjs.com/package/fusioncharts
- Issues:
- Visual Studio (Used Community Edition 2022 - 17.6.1)
- Start by referring to the Blazor documentation link for a detailed guide on setting up and installing the necessary dependencies.
- Clone the code repository from (https://github.com/fusioncharts/blazor-fusioncharts) to your local machine.
- Windows Installation: If you're on Windows, ensure that the following workloads are selected during the Visual Studio installation:
- ASP.NET and Web development
- Azure Development
- .NET Desktop
- After installation, launch Visual Studio and choose "Open a project or solution." Navigate to the 'BlazorApp1.sln' file in the extracted folder. Run the BlazorApp1 by clicking the run button in the toolbar.
- MacOS or Linux Installation: For MacOS or Linux users, run the 'dotnet watch' command from your project directory in the terminal.
- Open your preferred web browser and navigate to the appropriate address to view and interact with your Blazor app.
- Open the Project in Visual Studio.
- Click on Setting icon in the top-right and then click on Options.
- Navigate to NuGet Package Manager and select Package Sources from the left panel of the Options window opened.
- Click on the '+' symbol at the top right of the Package Sources window.
- At the Name field add the name of the package source as 'myget.org' and at the Source field paste the myGet package link.
- Click on Update and then click on OK.
- Under Tools click on NuGet Package Manager and select Manage NuGet Packages for Solution. Now change the project source to myget.org in the top-right.
- Move to Browse tab of the same window , enter the credentials when prompted and install the package BlazorApp1.
The application's operational flow can be described as follows:
-
Create a new blazor application.
-
Verify the existence of the FusionCharts package at the below loctions, if the package exists, remove it.
- For Windows: C:\Users\XXX.nuget\packages
- For macOS and Linux: ~/.nuget/packages
-
Check if there is an existing fusioncharts package in the local at this location "C:\Users\XXX.nuget\packages" for Windows and for mac and linux the location is "~/.nuget/packages". If so delete the package.
-
Install the latest package from Nuget.org.
-
Upon successful installation, we need to manually add the blazor-fusionCharts.js file from "C:\Users\XXX.nuget\packages\blazorfusioncharts\1.0.0\staticwebassets" or "~/.nuget/packages/blazorfusioncharts/1.0.0/staticwebassets/" to your app's wwwroot folder.
-
In _Host.cshtml file the below 2 script tags has to be added. You can even keep fusioncharts.js locally if you have downloaded the zip from the website, in that case you keep update the script tag to point to the location similar to blazor-fusionCharts.js.
<script type="text/javascript" src="https://cdn.fusioncharts.com/fusioncharts/latest/fusioncharts.js"></script> <script src="~/blazor-fusionCharts.js"></script>
-
In _Imports.razor file, add the FusionChartsInterop:
@using FusionCharts.FusionChartsInterop
-
In Program.cs file, add the FusionCharts service:
builder.Services.AddScoped<FusionCharts.FusionChartsInterop.FusionChartsService>(); builder.Services.AddHttpClient();
We have to write the logic to render a FusionCharts inside the Index.razor file. Inorder to render your own chart, edit this file.
Here is the code to render a time chart:
private async Task renderTimeCharts()
{
dynamic myChartConfig = new System.Dynamic.ExpandoObject();
dynamic myDataSource = new System.Dynamic.ExpandoObject();
dynamic myChart = new System.Dynamic.ExpandoObject();
dynamic myEvent = new System.Dynamic.ExpandoObject();
dynamic myCategories = new System.Dynamic.ExpandoObject();
dynamic myDataSet = new System.Dynamic.ExpandoObject();
myChartConfig.id = "stockRealTimeChart";
myChartConfig.type = "realtimeline";
myChartConfig.renderAt = "chartContainer4";
myChartConfig.width = 700;
myChartConfig.height = 400;
myChartConfig.dataFormat = "json";
myChart.caption = "Real-time stock price monitor";
myChart.subCaption = "Harry's SuperMart";
myChart.xAxisName = "Time";
myChart.yAxisName = "Stock Price";
myChart.refreshinterval = 1;
myChart.yaxisminvalue = 35;
myChart.yaxismaxvalue = 36;
myChart.numdisplaysets = 10;
myChart.labeldisplay = "rotate";
myChart.showRealTimeValue = 0;
myChart.theme = "fusion";
myCategories = new[] { new { catagory = new[] { new { label = "Day Start" } } } };
myEvent.initialized = "function() { updateTimeChartData() }";
myDataSource.chart = myChart;
myDataSource.dataset = new[] { new { data = new[] { new { value = "35.3" } } } };
myChartConfig.dataSource = myDataSource;
myChartConfig.events = myEvent;
String chartConfig = System.Text.Json.JsonSerializer.Serialize(myChartConfig);
await fusionChartsService.renderChart(chartConfig);
}
Invoking the generic method from Index.razor file:
await fusionChartsService.CallFusionChartsFunction("chartType", "CHART_ID");
The above method call is directed to the FusionChartsService.cs file which is a generic method calling another method generic method written in blazor-fusionCharts.js, and its implentation is:
public async Task<String> CallFusionChartsFunction(String functionName, String chartId, params object[] args)
{
String result = await _jsruntime.InvokeAsync<String>("FusionCharts.invokeChartFunction", functionName, chartId, args);
return result;
}
The generic method which is used to call any FusionCharts methods is embedded inside the blazor-fusioncharts.js file as shown:
window.FusionCharts.invokeChartFunction = (functionName, chartID, ...args) => {
let currentChart = FusionCharts(chartID),
result;
if (args.length > 0 && args[0].type === CALLBACK) {
let { event, fn } = args[0];
let callbackFn = parseFunction(null, fn);
result = currentChart[functionName].call(currentChart, event, callbackFn);
return String(result);
} else {
result = currentChart[functionName].apply(currentChart, ...args);
if (typeof result === "object") {
try {
result = JSON.stringify(result);
} catch (error) {
console.log(error);
}
}
return String(result);
}
};
There are two ways to attach event listeners to Fusioncharts:
To invoke a JavaScript method upon an event trigger, we have to follow the steps below:
- Generate a JavaScript file within the wwwroot directory that encompasses the implementation of the event handler method.
- Include the above created file as script tag in the _Host.cshtml. Here the created file name is custom.js present in wwwroot folder.
<script src="~/custom.js"></script>
- Implement the JavaScript function to activate it when the event is triggered.
- Execute an anonymous function to invoke the JS method upon event trigger.
Please use the 'function()' format for the function definition in JavaScript. Arrow functions isn't supported out of the box but it can be added simply by extending the regex in the blazor-fusioncharts. Please reach out to us in case of any any query.
myEvent.dataPlotClick = "function() { randomF();}";
To invoke a Blazor method upon an event trigger, we have to follow the steps below:
- Create an instance inside Index.razor file as shown below.
public static Index _instance;
- Instantiate the instance inside the constructor to refer to the current file/page name where it is being applied.
public <CurrentPageName>()
{
_instance = this;
}
- Implement a JSInvokable static method to invoke a non-static method using the instance.
[JSInvokable("ChangeData")]
public static async Task ChangeData()
{
await _instance.NonStaticMethod();
}
- Code the non-static method to perform any functionality, here we call the generic method to invoke FusionCharts methods.
public async Task NonStaticMethod()
{
await fusionChartsService.CallFusionChartsFunction("setChartAttribute", "CHART_ID", "caption", "new-caption");
}
- Now we are writing an anonymous function to call the Blazor method upon event trigger. Here 'DotNet' is available in the global scope of JavaScript.
myEvent.dataPlotClick = "function() { DotNet.invokeMethodAsync('BlazorApp1', 'ChangeData') }";
The addEventListener method listens to events across all FusionCharts instances on a page and executes custom functions when an event is triggered.
The generic method implemented above can be used to add a custom event listener which invokes a callback method and here it is:
var jsonData = new { type="callback", eventname = "dataPlotClick", fn = "function() {console.log('I am a callback function')}" };
await fusionChartsService.CallFusionChartsFunction("addEventListener", "CHART_ID", jsonData);
Below code snippet demonstrates the callback method implementation upon the event trigger.
if (args.length > 0 && args[0].type === CALLBACK) {
let { event, fn } = args[0];
let callbackFn = parseFunction(null, fn);
result = currentChart[functionName].call(currentChart, event, callbackFn);
return String(result);
}
setDataStore() : This method is used in TimeSeries and FusionGrid, this method takes data and schema from as input from the external files and creates a data source and a data table so as to render the chart.
Initially an empty data source is created in the Index.razor file as shown:
myDataSource.data = new {};
Below is the code snippet to read the contents of the external data and schema files. Also the method setDataStore() is invoked:
String dataFilePath = "./data.json";
String schemeFilePath = "./schema.json";
String dataContent = File.ReadAllText(dataFilePath);
String schemaContent = File.ReadAllText(schemeFilePath);
await fusionChartsService.setDataStore("chartId", dataContent, schemaContent);
Upon invoking the setDataStore() method above, it leads to the below code snippet in the FusionChartsService.cs file which in turn invokes another user-defined method in the blazor-fusioncharts.js:
public async Task setDataStore(String id, params object[] args){
await _jsruntime.InvokeVoidAsync("FusionCharts.setDataStore", id, args);
}
Finally, the functionality of setDataStore is implemented in the blazor-fusioncharts.js.
The code includes the creation of new data store and the parsing of data and schema to json.
A new data table is created with the data and schema and rendered it to the chart.
window.FusionCharts.setDataStore = (id, args) => {
let currentChart = FusionCharts(id);
let fusionDataStore = new FusionCharts.DataStore();
let data = JSON.parse(args[0]);
let schema = JSON.parse(args[1]);
let fusionTable = fusionDataStore.createDataTable(data, schema);
currentChart.setChartData({data: fusionTable});
};
resizeTo() : Resizes the chart to the specified width and height. While invoking the method there is a circular json object exception due to which it will throw error inside the generic method.
In order to mitigate the issue of circular deps in the FusionCharts, you can add your method definition where no data is returned back to the JS environment. This is caused due to the fact that certain methods return JSON which contain circular deps in FusionCharts and serialising a circular deps JSON isn't possible.
This method is invoked in the Index.razor file directly as below:
await fusionChartsService.resizeTo("chartId", 450, 500);
It then leads to the FusionChartsService.cs file where inturn invokes the method which will not return anything as returned object json is having circular references.
public async Task resizeTo(String id, params object[] args){
await _jsruntime.InvokeVoidAsync("FusionCharts.resizeTo", id, args);
}
The actual implementation is in the blazor-fusioncharts.js file which invokes the resizeTo method with the height and width parameters.
window.FusionCharts.resizeTo = (id, args) => {
let currentChart = FusionCharts(id);
currentChart.resizeTo(args[0], args[1]);
};
Annotations are user-defined objects or shapes drawn on a chart. They are used to increase the visual appeal of our charts and make them more informative. Annotations help end users interpret charts better.
Annotations are defined inside the annotations object. This object has an array of groups, and each group element has a unique id. The groups object contains an array of items, each of which contains information on one specific annotation in the chart.
Here we have created an external json file which contains the chart data and we implemented a button when clicked renders the chart with the annotation.
In the Index.razor file, firstly the data is read from the json file and the chart is rendered as follows:
string jsonUrl = navigationManager.ToAbsoluteUri("demo1.json").ToString();
dynamic myDataSource = jsonUrl;
await fusionChartsService.renderChart(chartConfig);
await fusionChartsService.CallFusionChartsFunction("setJSONUrl", "demoId", jsonUrl);
Now there is a user-defined method addAnnotaotion() which acts renders the chart by adding an item or a group upon button click. Here is the sample where an item is added:
private async Task addAnnotation(){
await fusionChartsService.addAnnotations("addItem", "demoId", "infobar", new {
id = "label1",
align= "RiGHT",
type= "text",
text= "Messi added{br}roughly 7 Goals from{br}his shot quality",
fillcolor= "#2F9AC4",
rotate= "90",
x= "$dataset.1.set.1.endx+65",
y= "$dataset.0.set.5.y"
}, true);
}
The flow leads to FusionChartsService.cs file and its implementation is as follows:
public async Task addAnnotations(String functionName, String id, params object[] args){
await _jsruntime.InvokeVoidAsync("FusionCharts.addAnnotations", functionName, id, args);
}
Finally the user-defined addAnnotations() is invoked to add either an item or a group to the rendered chart:
window.FusionCharts.addAnnotations = (functionName, id, args) => {
let annotations = FusionCharts(id).annotations;
annotations[functionName].apply(annotations, args);
};
The functionality to trigger the Cancel Events is implemented in Blazor, which disposes the event that is already triggered on the chart. In the Index.razor file, the functionality of the event that has to be disposed is as follows:
myEvent.dataPlotClick = "function() {DotNet.invokeMethodAsync('BlazorApp2TestQA2', 'ChangeData')}";
myEvent.beforeDispose = "function(e) { console.log(e); e.preventDefault() }";
myEvent.disposeCancelled = "function() { console.log('dispose cancelled') }";
Upon a button click, the event can be canclelled by invoking the callDispose() method whose implementation is attached below:
private async Task callDispose(){
await fusionChartsService.CallFusionChartsFunction("dispose", "demoId");
}
Note: Any method that we invoke that is manipulating or interacting with the chart data then it has to be called after the chart is rendered which means it has to be called after the "loaded" or "renderComplete" event has triggered.
Here is the link to an example that demonstrates the above point.
https://github.com/fusioncharts/blazor-fusioncharts/blob/feature/examples/examples/demo/Pages/Adding-Blazor-and-JS-functions-to-events-By-Sanskar
- Explore 20+ pre-built business specific dashboards for different industries like energy and manufacturing to business functions like sales, marketing and operations here.
- See Data Stories built using FusionCharts’ interactive JavaScript visualizations and learn how to communicate real-world narratives through underlying data to tell compelling stories.
There is a license activation mechanism followed by FusionCharts. This means that if you are an active customer then you have to provide license keys in your project to remove the watermark.
To activate your license follow these steps:
- Download the latest version of FusionCharts for your prefered framework.
- Embed the library in your project.
- Add the license key to your project, especially where you have instantiated FusionCharts.
- Download and install long term support version of dotnet from https://dotnet.microsoft.com/en-us/download. ( Version 6.0 was the LTS during the time of research )
- Navigate to /BlazopApp1 directory and open the terminal (or command prompt).
- Run
dotnet build
to build the project. - Run
dotnet run
to run the project.
- 'dotnet nuget locals all --clear' can be useful in case installing a specific version for FusionCharts throws an error such as, "Unable to find the package". The command clears all the packages that were installed locally, including any cache. And as a safety net, please consider backing up packages directory in your system before executing this command.