Currently, I am working with a Kendo column chart that has multiple series per category.
My goal is to position Kendo chart series item labels on top regardless of their value. By default, these labels are placed at the end of each chart item, appearing on top of columns for positive values and at the bottom for negatives.
https://i.sstatic.net/SlSZn.png
app.component.html
<kendo-chart>
<kendo-chart-category-axis>
<kendo-chart-category-axis-item [labels]="{ margin: { top: 10 } }">
</kendo-chart-category-axis-item>
</kendo-chart-category-axis>
<kendo-chart-value-axis>
<kendo-chart-value-axis-item>
</kendo-chart-value-axis-item>
</kendo-chart-value-axis>
<kendo-chart-series>
<kendo-chart-series-item *ngFor="let groupedResult of groupedData"
[data]="groupedResult.items"
field="income"
type="column"
categoryField="clientName"
noteTextField="income">
<kendo-chart-series-item-labels format="C0">
</kendo-chart-series-item-labels>
<kendo-chart-series-item-notes position="bottom"
[icon]="{ visible: false }"
[line]="{ width: 0 }"
[label]="noteLabel">
</kendo-chart-series-item-notes>
</kendo-chart-series-item>
</kendo-chart-series>
</kendo-chart>
app.component.ts
import { Component, OnInit } from '@angular/core';
import * as _ from 'lodash';
export type TrendItem = {
clientName: string;
year: number;
period: number;
income: number;
};
export type GroupedTrendItem = {
value: { year: number; period: number };
items: TrendItem[];
};
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
})
export class AppComponent implements OnInit {
public trendItems: TrendItem[] = [
{
clientName: 'Client1',
year: 2020,
period: 3,
income: -35,
},
{
clientName: 'Client1',
year: 2020,
period: 4,
income: 40,
},
{
clientName: 'Client2',
year: 2020,
period: 1,
income: -15,
},
{
clientName: 'Client2',
year: 2020,
period: 2,
income: 20,
},
{
clientName: 'Client2',
year: 2020,
period: 3,
income: 15,
},
{
clientName: 'Client3',
year: 2020,
period: 2,
income: 50,
},
{
clientName: 'Client3',
year: 2020,
period: 3,
income: -35,
},
{
clientName: 'Client3',
year: 2020,
period: 4,
income: 20,
},
];
public noteLabel = {
color: 'black',
content: e => `Q${e.dataItem.period} ${e.dataItem.year}`,
font: '12px Arial',
margin: -30,
};
private getGroupedTrends() {
const groupedTrendItems = this.trendItems.reduce((acc, trendItem) => {
let element = acc.find(el => el.value.year === trendItem.year
&& el.value.period === trendItem.period
);
if (element) {
element.items.push(trendItem);
} else {
acc.push({
value: { year: trendItem.year, period: trendItem.period },
items: [trendItem],
});
}
return acc;
}, [] as GroupedTrendItem[]);
return _.sortBy(groupedTrendItems, [
item => item.value.year,
item => item.value.period,
]);
}
public groupedData = this.getGroupedTrends();
public ngOnInit() {
console.log(this.groupedData);
}
}
You can test this code by clicking here.
Currently, the labels do not offer an available 'top' option for the SeriesLabelsPosition
component when working with a column chart (although the reason for this remains unclear to me).
If the period display is not necessary, the SeriesNotesComponent
can be used as I currently employ it for periods, allowing for the assignment of position="top"
without any issues.
Therefore, my question is how to ensure labels are always displayed on top of the column regardless of their value.