hello
please add support for bind pivotgrid to datatable or expando objects (local mode)
I had already tried using reflection via dataTemplate to access the ColumnGroup and RowGroup properties. It would be nice if in future versions, if possible, these were accessible directly and without having to use reflection for efficiency reasons. Expose the current field as well.
In addition to this, it would be convenient to know which row and column they refer to, in order to know which field of the Pivot dataset relates to the calculation performed, and apply custom logic to them.
In summary, expose: ColumnGroup, RowGroup, and the current field.
When using local data binding, all defined PivotGrid measures are checked by default and render in the Grid.
Please provide the ability to define measures, which are not checked and visible in the Grid area by default.
The Expand/Collapse icon of the PivotGrid is always a font one. I am using SVG icons in my app and I don't see the any icon in the toggle button.
===
ADMIN EDIT
===
A workaround for the time being is to register the Font icons stylesheet even if you are using SVG icons.
It would be nice to be able to customize the comparer used to display data in a specific order.
I think by default it uses a simple alphabetic comparison
But we have a lot of data using alpha and numeric information like:
And the user wants data in the numeric order, so we often implement our own comparer everywhere for it to work.
The PivotGrid doesn't seem to provide a way to customize the order of data even with a provider Local, ordering the source in a specific way before giving it to the component doesn't work either.
Thanks
Thomas
The PivotGrid supports multiple Measures for the same Field on initial load. However, if the user makes a change in the configurator, then only the first Measure per Field remains visible.
===
TELERIK edit: Apart from not using a PivotGrid configurator, another possible workaround is to use custom UI instead of a configurator. Recreate the component to apply the changes:
<label class="k-checkbox-label">
<TelerikCheckBox @bind-Value="@ShowCity"
OnChange="@OnPivotGridConfigurationChanged" />
Show City Column
</label>
<label class="k-checkbox-label">
<TelerikCheckBox @bind-Value="@ShowProduct"
OnChange="@OnPivotGridConfigurationChanged" />
Show Product Row
</label>
@if (RenderPivotGrid)
{
<TelerikPivotGrid Data="@PivotData"
DataProviderType="@PivotGridDataProviderType.Local"
ColumnHeadersWidth="240px">
<PivotGridColumns>
<PivotGridColumn Name="@nameof(PivotModel.Country)" Title="Country" />
@if (ShowCity)
{
<PivotGridColumn Name="@nameof(PivotModel.City)" Title="City" />
}
</PivotGridColumns>
<PivotGridRows>
<PivotGridRow Name="@nameof(PivotModel.Category)" Title="Category" />
@if (ShowProduct)
{
<PivotGridRow Name="@nameof(PivotModel.Product)" />
}
</PivotGridRows>
<PivotGridMeasures>
<PivotGridMeasure Name="@nameof(PivotModel.ContractValue)"
Title="Contract Value"
Aggregate="@PivotGridAggregateType.Sum" />
<PivotGridMeasure Name="@nameof(PivotModel.ContractValue)"
Title="Contract Value"
Aggregate="@PivotGridAggregateType.Average" />
<PivotGridMeasure Name="@nameof(PivotModel.ContractProfit)"
Title="Contract Value"
Aggregate="@PivotGridAggregateType.Sum" />
<PivotGridMeasure Name="@nameof(PivotModel.ContractProfit)"
Title="Contract Value"
Aggregate="@PivotGridAggregateType.Average" />
</PivotGridMeasures>
</TelerikPivotGrid>
}
@code {
private List<PivotModel> PivotData { get; set; } = new List<PivotModel>();
private bool RenderPivotGrid { get; set; } = true;
private bool ShowCity { get; set; }
private bool ShowProduct { get; set; }
private async Task OnPivotGridConfigurationChanged()
{
RenderPivotGrid = false;
await Task.Delay(1);
RenderPivotGrid = true;
}
protected override void OnInitialized()
{
var dataItemCount = 100;
var categoryCount = 2;
var productCount = 4 + 1;
var countryCount = 2;
var cityCount = 4 + 1;
var rnd = Random.Shared;
for (int i = 1; i <= dataItemCount; i++)
{
var productNumber = rnd.Next(1, productCount);
var cityNumber = rnd.Next(1, cityCount);
PivotData.Add(new PivotModel()
{
Category = $"Category {productNumber % categoryCount + 1}",
Product = $"Product {productNumber}",
Country = $"Country {cityNumber % countryCount + 1}",
City = $"City {cityNumber}",
ContractDate = DateTime.Now.AddDays(-rnd.Next(1, 31)).AddMonths(-rnd.Next(1, 12)).AddYears(-rnd.Next(0, 5)),
ContractValue = rnd.Next(456, 987),
ContractProfit = rnd.Next(43, 98)
});
}
base.OnInitialized();
}
public class PivotModel
{
public string Category { get; set; } = null!;
public string Product { get; set; } = null!;
public string Country { get; set; } = null!;
public string City { get; set; } = null!;
public DateTime ContractDate { get; set; }
public decimal ContractValue { get; set; }
public decimal ContractProfit { get; set; }
}
}
The PivotGrid layout and cell alignment break when filtering expanded child columns by a value that exists only in some of the columns.
Here is a test page:
<TelerikPivotGridContainer>
<TelerikPivotGridConfiguratorButton></TelerikPivotGridConfiguratorButton>
<TelerikPivotGridConfigurator></TelerikPivotGridConfigurator>
<TelerikPivotGrid Data="@PivotGridData" DataProviderType="@PivotGridDataProviderType.Local"
@ref="PivotGridRef" ColumnHeadersWidth="100px" RowHeadersWidth="130px">
<ColumnHeaderTemplate>
@{
var ctx = (PivotGridColumnHeaderTemplateContext)context;
int underscoreIndex = ctx.Text.IndexOf("-");
string text = ctx.Text;
if (underscoreIndex > 0)
{
text = text.Replace(text.Substring(0, underscoreIndex + 1), "");
<span>@text</span>
}
else
{
<span>@ctx.Text</span>
}
}
</ColumnHeaderTemplate>
<DataCellTemplate Context="dataCellContext">
@{
var c = (PivotGridDataCellTemplateContext)dataCellContext;
var amt = c.Value == null ? (0m).ToString("C2") : ((decimal)c.Value).ToString("C2");
}
<div style="text-align: right;">
@amt
</div>
</DataCellTemplate>
<PivotGridRows>
<PivotGridRow Name="@nameof(PivotGridModel.Station)" Title="Station" />
</PivotGridRows>
<PivotGridColumns>
<PivotGridColumn Name="@nameof(PivotGridModel.Year)" Title="Year" HeaderClass="year-header" />
<PivotGridColumn Name="@nameof(PivotGridModel.MonthName)" Title="Month" />
</PivotGridColumns>
<PivotGridMeasures>
<PivotGridMeasure Name="@nameof(PivotGridModel.Rate)" Title="Total"
Aggregate="@PivotGridAggregateType.Sum" />
</PivotGridMeasures>
</TelerikPivotGrid>
</TelerikPivotGridContainer>
@code
{
private TelerikPivotGrid<PivotGridModel>? PivotGridRef { get; set; }
private List<PivotGridModel> PivotGridData { get; set; } = new();
protected override async Task OnInitializedAsync()
{
var dataItemCount = 10000;
var stationCount = 30;
var rnd = Random.Shared;
for (int i = 1; i <= dataItemCount; i++)
{
var stationNumber = rnd.Next(1, stationCount);
PivotGridData.Add(new PivotGridModel()
{
Station = $"Station {stationNumber}",
ContractMonth = DateTime.Today.AddMonths(-rnd.Next(0, 13)),
Rate = rnd.Next(123, 987) * 1.23m
});
}
PivotGridRef?.Rebind();
await base.OnInitializedAsync();
}
public class PivotGridModel
{
public DateTime ContractMonth { get; set; }
public int Year => ContractMonth.Year;
public int Month => ContractMonth.Month;
public string MonthName => $"{Month}-{ContractMonth.ToString("MMMM")}";
public string Station { get; set; } = string.Empty;
public decimal? Rate { get; set; }
}
}