Working with Data in Blazor Charts Component
13 Sep 202424 minutes to read
The Chart uses SfDataManager, which supports both RESTful JSON data services binding and IEnumerable binding. The DataSource value can be set using either SfDataManager property values or a list of business objects.
It supports the following data binding methods:
- List binding
- Remote data
List binding
An IEnumerable object can be assigned to the DataSource property. The list data source can alternatively be given as an instance of SfDataManager or by using SfDataManager or as a component of the SfDataManager or by using SfDataManager. The data fields should now be mapped to the XName and YName properties.
@using Syncfusion.Blazor.Charts
<SfChart Title="Inflation - Consumer Price" Width="60%">
<ChartPrimaryXAxis IntervalType="IntervalType.Years" LabelFormat="yyyy" ValueType="Syncfusion.Blazor.Charts.ValueType.DateTime">
</ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries DataSource="@ConsumerReports" XName="XValue" YName="YValue" Type="ChartSeriesType.Line">
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code{
public class ChartData
{
public DateTime XValue { get; set; }
public double YValue { get; set; }
}
public List<ChartData> ConsumerReports = new List<ChartData>
{
new ChartData { XValue = new DateTime(2005, 01, 01), YValue = 21 },
new ChartData { XValue = new DateTime(2006, 01, 01), YValue = 24 },
new ChartData { XValue = new DateTime(2007, 01, 01), YValue = 36 },
new ChartData { XValue = new DateTime(2008, 01, 01), YValue = 38 },
new ChartData { XValue = new DateTime(2009, 01, 01), YValue = 54 },
new ChartData { XValue = new DateTime(2010, 01, 01), YValue = 57 },
new ChartData { XValue = new DateTime(2011, 01, 01), YValue = 70 },
};
}
NOTE
By default, SfDataManager uses BlazorAdaptor for list data-binding.
ExpandoObject binding
Chart is a generic component which is strongly bound to a model type. There are cases when the model type is unknown during compile time. In such circumstances data can be bound to the chart as a list of ExpandoObjects. The ExpandoObject can be bound to chart by assigning to the DataSource property.
@using Syncfusion.Blazor.Charts
@using System.Dynamic
<SfChart>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category" />
<ChartSeriesCollection>
<ChartSeries DataSource="@MedalDetails" XName="X" YName="Y" Type="ChartSeriesType.Column">
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code{
private List<string> countries = new List<string> { "South Korea", "India", "Germany", "Italy", "Russia" };
private Random randomNum = new Random();
public List<ExpandoObject> MedalDetails { get; set; } = new List<ExpandoObject>();
protected override void OnInitialized()
{
MedalDetails = Enumerable.Range(0, 5).Select((x) =>
{
dynamic d = new ExpandoObject();
d.X = countries[x];
d.Y = randomNum.Next(20, 80);
return d;
}).Cast<ExpandoObject>().ToList<ExpandoObject>();
}
}
DynamicObject binding
Chart supports DynamicObject data source when the model type is unknown. The DynamicObject can be bound to chart by assigning to the DataSource property.
@using Syncfusion.Blazor.Charts
@using System.Dynamic
<SfChart>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.DateTime"></ChartPrimaryXAxis>
<ChartPrimaryYAxis></ChartPrimaryYAxis>
<ChartSeriesCollection>
<ChartSeries DataSource="MedalDetails" XName="X" YName="Y" Type="ChartSeriesType.Area"></ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code{
private List<DateTime> Dates = new List<DateTime> { new DateTime(2005, 01, 01), new DateTime(2006, 01, 01),
new DateTime(2007, 01, 01), new DateTime(2008, 01, 01), new DateTime(2009, 01, 01), new DateTime(2010, 01, 01), new DateTime(2011, 01, 01) };
public DateTime[] Value = new DateTime[] { new DateTime(2006, 01, 01), new DateTime(2008, 01, 01) };
private Random randomNum = new Random();
public List<DynamicDictionary> MedalDetails = new List<DynamicDictionary>() { };
protected override void OnInitialized()
{
MedalDetails = Enumerable.Range(0, 5).Select((x) =>
{
dynamic d = new DynamicDictionary();
d.X = Dates[x];
d.Y = randomNum.Next(20, 80);
return d;
}).Cast<DynamicDictionary>().ToList<DynamicDictionary>();
}
public class DynamicDictionary : DynamicObject
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name;
return dictionary.TryGetValue(name, out result);
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
public override System.Collections.Generic.IEnumerable<string> GetDynamicMemberNames()
{
return this.dictionary?.Keys;
}
}
}
Remote data
Assign service data as an instance of SfDataManager to the DataSource property to bind remote data to the chart component. Provide the endpoint Url to communicate with a remote data source.
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Charts
@using System.Dynamic
<SfChart>
<SfDataManager Url="https://services.odata.org/V4/Northwind/Northwind.svc/Orders" Adaptor="Adaptors.ODataV4Adaptor"></SfDataManager>
<ChartPrimaryXAxis Title="Orders" ValueType="Syncfusion.Blazor.Charts.ValueType.Category"
RangePadding="ChartRangePadding.Additional"></ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries XName="OrderID" YName="Freight" Type="ChartSeriesType.Column"></ChartSeries>
</ChartSeriesCollection>
</SfChart>
Binding with OData services
OData is a standardized data creation and consumption protocol. The SfDataManager can be used to retrieve data from an OData service. For remote data binding using the OData service, see the code below.
Binding with OData v4 services
The SfDataManager can retrieve and consume OData v4 services, which is an upgraded version of OData protocols. Refer to the OData documentation for additional information on OData v4 services. To bind an OData v4 service, use the ODataV4Adaptor.
Web API
The WebApiAdaptor can be used to bind a chart to a Web API created using an OData endpoint.
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Charts
<SfChart>
<SfDataManager Url="https://blazor.syncfusion.com/services/production/api/Orders" Adaptor="Adaptors.WebApiAdaptor"></SfDataManager>
<ChartPrimaryXAxis Title="Orders" ValueType="Syncfusion.Blazor.Charts.ValueType.Category"
></ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries XName="OrderID" YName="Freight" Type="ChartSeriesType.Column"></ChartSeries>
</ChartSeriesCollection>
</SfChart>
Sending additional parameters to the server
To create a data request with a custom parameter, add additional parameters to the Query object and assign it to the chart’s Query property.
The following sample code shows how to send parameters using the Query property in the series.
@using Syncfusion.Blazor.Data
@using Syncfusion.Blazor.Charts
<SfChart>
<SfDataManager Url="https://services.odata.org/V4/Northwind/Northwind.svc/Orders" Adaptor="Adaptors.ODataV4Adaptor"></SfDataManager>
<ChartPrimaryXAxis Title="Orders" ValueType="Syncfusion.Blazor.Charts.ValueType.Category"
RangePadding="ChartRangePadding.Additional"></ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries Query="ChartQuery" XName="OrderID" YName="Freight" Type="ChartSeriesType.Column"></ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code{
public Query ChartQuery { get; set; }
protected override void OnInitialized()
{
ChartQuery = new Query().Take(10).Where("Freight", "GreaterThan", 300, false);
}
}
Entity Framework
Entity Framework acts as a modern object-database mapper for .NET. This section explains how to bind data to the chart component from a Microsoft SQL Server database.
Create DBContext class
To connect to a Microsoft SQL Server database, the first step is to construct a DBContext class named OrderContext.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using EFChart.Data;
namespace EFChart.Data
{
public class OrderContext : DbContext
{
public virtual DbSet<Order> Orders { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
// Configures the context to connect to a Microsoft SQL Serve database
optionsBuilder.UseSqlServer(@"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename='D:\blazor\EFTreeMap\App_Data\NORTHWND.MDF';Integrated Security=True;Connect Timeout=30");
}
}
}
public class Order
{
[Key]
public int? OrderID { get; set; }
[Required]
public string CustomerID { get; set; }
[Required]
public int EmployeeID { get; set; }
}
}
Create data access layer to perform data operation
Then construct a class named OrderDataAccessLayer that will serve as a data access layer for retrieving records from the database table.
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static BlazorApp1.Data.OrderContext;
using EFChart.Data;
namespace EFChart.Data
{
public class OrderDataAccessLayer
{
OrderContext db = new OrderContext();
//To Get all Orders details
public DbSet<Order> GetAllOrders()
{
try
{
return db.Orders;
}
catch
{
throw;
}
}
}
}
Creating Web API Controller
Need to create a Web API Controller that allows the chart to receive data directly from the Entity Framework.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using static BlazorApp1.Data.OrderContext;
using EFChart.Data;
namespace EFChart.Controller
{
[Route("api/[controller]")]
[ApiController]
public class DefaultController : ControllerBase
{
OrderDataAccessLayer db = new OrderDataAccessLayer();
[HttpGet]
public object Get()
{
IQueryable<Order> data = db.GetAllOrders().AsQueryable();
var count = data.Count();
var queryString = Request.Query;
if (queryString.Keys.Contains("$inlinecount"))
{
StringValues Skip;
StringValues Take;
int skip = (queryString.TryGetValue("$skip", out Skip)) ? Convert.ToInt32(Skip[0]) : 0;
int top = (queryString.TryGetValue("$top", out Take)) ? Convert.ToInt32(Take[0]) : data.Count();
return new { Items = data.Skip(skip).Take(top), Count = count };
}
else
{
return data;
}
}
}
}
Add Web API Controller services in Startup.cs
As shown below, open the Startup.cs file and add the services and endpoints necessary for Web API Controller.
using EFChart.Data;
using Newtonsoft.Json.Serialization;
namespace BlazorApplication
{
public class Startup
{
....
....
public void ConfigureServices(IServiceCollection services)
{
....
....
services.AddSingleton<OrderDataAccessLayer>();
// Adds services for controllers to the specified Microsoft.Extensions.DependencyInjection.IServiceCollection.
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
....
....
app.UseEndpoints(endpoints =>
{
// Adds endpoints for controller actions to the Microsoft.AspNetCore.Routing.IEndpointRouteBuilder
endpoints.MapDefaultControllerRoute();
.....
.....
});
}
}
}
Configure chart component
Use the DataSource property or SfDataManager to bind data to the chart.
For instance, to bind data directly from the data access layer class OrderDataAccessLayer, assign the DataSource property to be OrderData.GetAllOrders().
@using EFChart.Data;
@inject OrderDataAccessLayer OrderData;
@using Syncfusion.Blazor.Charts
<SfChart DataSource="@OrderData.GetAllOrders()">
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category">
</ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries XName="CustomerID" YName="OrderID" Type="ChartSeriesType.Column">
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
On the other hand, to configure the chart using Web API, provide the appropriate endpoint Url within SfDataManager along with Adaptor. In order to interact with the Web API and consume data from the Entity Framework effectively, WebApiAdaptor must be used.
@using Syncfusion.Blazor.Charts
@using Syncfusion.Blazor.Data
<SfChart>
<SfDataManager Url="api/Default" Adaptor="Syncfusion.Blazor.Adaptors.WebApiAdaptor">
</SfDataManager>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category">
</ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries XName="CustomerID" YName="OrderID" Type="ChartSeriesType.Column">
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
Observable collection
The ObservableCollection (dynamic data collection) provides notifications when items are added, removed, and moved. The implemented INotifyCollectionChanged provides notification when the dynamic changes of adding, removing, moving, and clearing the collection occur.
@using Syncfusion.Blazor.Charts
@using System.Collections.ObjectModel;
<SfChart @ref="ChartObj" Title="Olympic Medal Counts - RIO" Width="450px">
<ChartArea><ChartAreaBorder Width="0"></ChartAreaBorder></ChartArea>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category" Interval="1">
<ChartAxisMajorGridLines Width="0"></ChartAxisMajorGridLines>
<ChartAxisMajorTickLines Width="0"></ChartAxisMajorTickLines>
</ChartPrimaryXAxis>
<ChartPrimaryYAxis Title="Medal Count" Maximum="50" Interval="10">
<ChartAxisMajorTickLines Width="0"></ChartAxisMajorTickLines>
<ChartAxisLineStyle Width="0"></ChartAxisLineStyle>
</ChartPrimaryYAxis>
<ChartSeriesCollection>
<ChartSeries TooltipMappingName="MappingName" DataSource="@ChartPoints" XName="Country" YName="GoldMedal" Name="Gold" ColumnSpacing="0.1" Type="ChartSeriesType.Column">
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code {
SfChart ChartObj;
public ObservableCollection<ColumnChartData> ChartPoints { get; set; }
public class ColumnChartData
{
public string Country { get; set; }
public double GoldMedal { get; set; }
public static ObservableCollection<ColumnChartData> GetData()
{
ObservableCollection<ColumnChartData> ChartPoints = new ObservableCollection<ColumnChartData>()
{
new ColumnChartData { Country = "GBR", GoldMedal = 27 },
new ColumnChartData { Country = "CHN", GoldMedal = 26 },
new ColumnChartData { Country = "AUS", GoldMedal = 8 },
new ColumnChartData { Country = "RUS", GoldMedal = 19 }
};
return ChartPoints;
}
}
protected override void OnInitialized()
{
this.ChartPoints = ColumnChartData.GetData();
}
}
Empty points
Empty points are defined as data points having NaN values. Empty points can be customized using EmptyPointSettings property in series. Default Empty Point Mode is Gap.
@using Syncfusion.Blazor.Charts
<SfChart>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category">
</ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries DataSource="@SalesReports" XName="Month" YName="Sales" Type="ChartSeriesType.Column">
<ChartEmptyPointSettings Fill="blue" Mode="@Mode">
</ChartEmptyPointSettings>
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code{
public class ChartData
{
public string Month { get; set; }
public Nullable<double> Sales { get; set; }
}
public EmptyPointMode Mode = EmptyPointMode.Average;
public List<ChartData> SalesReports = new List<ChartData>
{
new ChartData{ Month= "Jan", Sales= 35 },
new ChartData{ Month= "Feb", Sales= 28 },
new ChartData{ Month= "Mar", Sales= double.NaN },
new ChartData{ Month= "Apr", Sales= 32 },
new ChartData{ Month= "May", Sales= 40 },
new ChartData{ Month= "Jun", Sales= 32 },
new ChartData{ Month= "Jul", Sales= 35 },
new ChartData{ Month= "Aug", Sales= double.NaN },
new ChartData{ Month= "Sep", Sales= 38 },
new ChartData{ Month= "Oct", Sales= 30 },
new ChartData{ Month= "Nov", Sales= 25 },
new ChartData{ Month= "Dec", Sales= 32 }
};
}
Customizing empty point
The Fill property specifies the color of EmptyPointSettings and the ChartEmptyPointBorder specifies Color and Width of border for EmptyPointSettings.
@using Syncfusion.Blazor.Charts
<SfChart>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category">
</ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries DataSource="@SalesReports" XName="Month" YName="Sales" Type="ChartSeriesType.Column">
<ChartEmptyPointSettings Fill="red" Mode="@Mode">
<ChartEmptyPointBorder Color="black" Width="2"></ChartEmptyPointBorder>
</ChartEmptyPointSettings>
</ChartSeries>
</ChartSeriesCollection>
</SfChart>
@code{
public class ChartData
{
public string Month { get; set; }
public Nullable<double> Sales { get; set; }
}
public EmptyPointMode Mode = EmptyPointMode.Average;
public List<ChartData> SalesReports = new List<ChartData>
{
new ChartData{ Month= "Jan", Sales= 35 },
new ChartData{ Month= "Feb", Sales= 28 },
new ChartData{ Month= "Mar", Sales= double.NaN },
new ChartData{ Month= "Apr", Sales= 32 },
new ChartData{ Month= "May", Sales= 40 },
new ChartData{ Month= "Jun", Sales= 32 },
new ChartData{ Month= "Jul", Sales= 35 },
new ChartData{ Month= "Aug", Sales= double.NaN },
new ChartData{ Month= "Sep", Sales= 38 },
new ChartData{ Month= "Oct", Sales= 30 },
new ChartData{ Month= "Nov", Sales= 25 },
new ChartData{ Month= "Dec", Sales= 32 }
};
}
NOTE
Refer to our Blazor Charts feature tour page for its groundbreaking feature representations and also explore our Blazor Chart Example to know various chart types and how to represent time-dependent data, showing trends at equal intervals.