Show Sum Label and Group Name for Stacked Chart Column Series
Environment
Product | Chart for Blazor |
Version |
4.5.0 +
(see section Notes for previous versions) |
Description
This knowledge base article answers the following questions:
- How to show the aggregated sum of a stacked Chart column?
- How to display the total (summed-up) value at the top of each stacked Chart column?
- How do you show stacked column series broken down by sub-category across the category axis?
- Can you label each stacked Chart column in a category group? How to align the group and column labels on the axis?
- How to draw an axis label for each individual
ChartSeries
column in the same category group?
Solution
The article suggests two scenarios with examples. Both of them use series labels for a different purpose. If users need to see the separate non-stacked series values, consider Chart tooltips.
- Display a sum of stacked Chart series above each stacked column
- Display a label on the horizontal Chart axis below each column
Aggregated Stack Column Label
Here is how to display the total sum of stacked Chart series above each stacked column:
- Configure Chart series stacking.
- Add a
<ChartSeriesLabels>
tag and define a label template for the series that will display at the top of each stacked column. This is the last<ChartSeries>
in the Chart declaration from a given stackGroup
. - In the series label template, render the
stackValue
property of the template argument object (context
).
<TelerikChart>
<ChartTitle Text="Work Items by Team and Period" />
<ChartSeriesItems>
<ChartSeries Data="@CowboysData"
Name="Cowboys Bugs"
Field="@nameof(ChartModel.Bugs)"
CategoryField="@nameof(ChartModel.DateValue)">
<ChartSeriesStack Group="Cowboys" Enabled="true" />
<ChartSeriesLabels Visible="true"
Position="@ChartSeriesLabelsPosition.InsideBase"
Rotation="-60"
Template="cowboysLabel"
Background="transparent">
<ChartSeriesLabelsMargin Top="80" />
</ChartSeriesLabels>
<ChartSeriesTooltip Visible="true">
<Template>
@context.FormattedValue bugs
</Template>
</ChartSeriesTooltip>
</ChartSeries>
<ChartSeries Data="@CowboysData"
Name="Cowboys Features"
Field="@nameof(ChartModel.Features)"
CategoryField="@nameof(ChartModel.DateValue)">
<ChartSeriesStack Group="Cowboys" Enabled="true" />
<ChartSeriesLabels Visible="true"
Template="stackSumLabel">
</ChartSeriesLabels>
<ChartSeriesTooltip Visible="true">
<Template>
@context.FormattedValue features
</Template>
</ChartSeriesTooltip>
</ChartSeries>
<ChartSeries Data="@SailorsData"
Name="Sailors Bugs"
Field="@nameof(ChartModel.Bugs)"
CategoryField="@nameof(ChartModel.DateValue)">
<ChartSeriesStack Group="Sailors" Enabled="true" />
<ChartSeriesLabels Visible="true"
Position="@ChartSeriesLabelsPosition.InsideBase"
Rotation="-60"
Template="sailorsLabel"
Background="transparent">
<ChartSeriesLabelsMargin Top="67" />
</ChartSeriesLabels>
<ChartSeriesTooltip Visible="true">
<Template>
@context.FormattedValue bugs
</Template>
</ChartSeriesTooltip>
</ChartSeries>
<ChartSeries Data="@SailorsData"
Name="Sailors Features"
Field="@nameof(ChartModel.Features)"
CategoryField="@nameof(ChartModel.DateValue)">
<ChartSeriesStack Group="Sailors" Enabled="true" />
<ChartSeriesLabels Visible="true"
Template="stackSumLabel">
</ChartSeriesLabels>
<ChartSeriesTooltip Visible="true">
<Template>
@context.FormattedValue features
</Template>
</ChartSeriesTooltip>
</ChartSeries>
</ChartSeriesItems>
<ChartCategoryAxes>
<ChartCategoryAxis Type="@ChartCategoryAxisType.Date"
BaseUnit="@ChartCategoryAxisBaseUnit.Months">
<ChartCategoryAxisLabels>
<ChartCategoryAxisLabelsMargin Top="80" />
</ChartCategoryAxisLabels>
</ChartCategoryAxis>
</ChartCategoryAxes>
<ChartValueAxes>
<ChartValueAxis Max="20" MajorUnit="4" />
</ChartValueAxes>
<ChartLegend Visible="true" Position="@ChartLegendPosition.Top" />
</TelerikChart>
@* Move JavaScript to a JS file in production apps *@
<script suppress-error="BL9992">
function cowboysLabel(context) {
return "Cowboys";
}
function sailorsLabel(context) {
return "Sailors";
}
function stackSumLabel(context) {
return "Sum: " + context.stackValue;
}
</script>
@code {
private List<ChartModel> CowboysData { get; set; } = new List<ChartModel>();
private List<ChartModel> SailorsData { get; set; } = new List<ChartModel>();
protected override void OnInitialized()
{
var rnd = new Random();
for (int i = 0; i < 3; i++)
{
CowboysData.Add(new ChartModel()
{
DateValue = DateTime.Today.AddMonths(-i),
Bugs = rnd.Next(5, 10),
Features = rnd.Next(5, 10)
});
SailorsData.Add(new ChartModel()
{
DateValue = DateTime.Today.AddMonths(-i),
Bugs = rnd.Next(3, 8),
Features = rnd.Next(3, 8)
});
}
base.OnInitialized();
}
public class ChartModel
{
public DateTime DateValue { get; set; }
public int Bugs { get; set; }
public int Features { get; set; }
}
}
Stack Group or Column Name as Custom Axis Label
Here is how to display an additional custom label on the horizontal Chart axis below each column. This approach doesn't require stacking and can be used with standalone column series too.
- Add a
<ChartSeriesLabels>
tag and define a label template for the series that will display at the bottom of each stacked column. This is the first<ChartSeries>
in the Chart declaration from a given stackGroup
. If you are not using stacking, then implement this step for all column series. - Set
Position="@ChartSeriesLabelsPosition.InsideBase"
to each<ChartSeriesLabels>
tag. - (optional) Set
Rotation
to each<ChartSeriesLabels>
tag. - (optional) Set
Background="transparent"
to each<ChartSeriesLabels>
tag. This will prevent label overlapping and fading if the columns are too close to one another. - Add a nested
<ChartSeriesLabelsMargin>
tag inside each<ChartSeriesLabels>
. Set theTop
margin parameter to anint
value. This margin will push the custom label below the horizontal Chart axis. If the label is rotated, then the top margin depends on the label length. If you set the same top margin in all series, the labels will be aligned on their bottom side. If you set different top margins, you can align the custom labels on their top side, with regard to the horizontal Chart axis. - Set the
Top
parameter of<ChartCategoryAxisLabelsMargin>
, so that it is equal or similar to the largestTop
value of all<ChartSeriesLabelsMargin>
tags.
<TelerikChart>
<ChartTitle Text="Work Items by Period" />
<ChartSeriesItems>
<ChartSeries Data="@CowboysData"
Name="Bugs"
Field="@nameof(ChartModel.Bugs)"
CategoryField="@nameof(ChartModel.DateValue)">
<ChartSeriesLabels Visible="true"
Position="@ChartSeriesLabelsPosition.InsideBase"
Rotation="-90"
Template="bugsLabel"
Background="transparent">
<ChartSeriesLabelsMargin Top="55" />
</ChartSeriesLabels>
<ChartSeriesTooltip Visible="true" />
</ChartSeries>
<ChartSeries Data="@CowboysData"
Name="Features"
Field="@nameof(ChartModel.Features)"
CategoryField="@nameof(ChartModel.DateValue)">
<ChartSeriesLabels Visible="true"
Position="@ChartSeriesLabelsPosition.InsideBase"
Rotation="-90"
Template="featuresLabel"
Background="transparent">
<ChartSeriesLabelsMargin Top="75" />
</ChartSeriesLabels>
<ChartSeriesTooltip Visible="true" />
</ChartSeries>
</ChartSeriesItems>
<ChartCategoryAxes>
<ChartCategoryAxis Type="@ChartCategoryAxisType.Date"
BaseUnit="@ChartCategoryAxisBaseUnit.Months">
<ChartCategoryAxisLabels>
<ChartCategoryAxisLabelsMargin Top="70" />
</ChartCategoryAxisLabels>
</ChartCategoryAxis>
</ChartCategoryAxes>
<ChartLegend Visible="true" Position="@ChartLegendPosition.Top" />
</TelerikChart>
@* Move JavaScript to a JS file in production apps *@
<script suppress-error="BL9992">
function bugsLabel(context) {
return "Bugs";
}
function featuresLabel(context) {
return "Features";
}
</script>
@code {
private List<ChartModel> CowboysData { get; set; } = new List<ChartModel>();
protected override void OnInitialized()
{
var rnd = new Random();
for (int i = 0; i < 6; i++)
{
CowboysData.Add(new ChartModel()
{
DateValue = DateTime.Today.AddMonths(-i),
Bugs = rnd.Next(5, 10),
Features = rnd.Next(5, 10)
});
}
base.OnInitialized();
}
public class ChartModel
{
public DateTime DateValue { get; set; }
public int Bugs { get; set; }
public int Features { get; set; }
}
}
Notes
Chart label templates require a different configuration for Telerik UI for Blazor versions before 4.5.0. If you are using an earlier version, then download the PDF documentation for your version, or browse an older version of the Chart Label Templates documentation.