Individual (conditional) cell back color
Environment
Product | Grid for Blazor, TreeList for Blazor |
Description
I want to set the backcolor of the cells on a cell by cell basis. In some cases, setting the color for the entire row can also work.
I want to apply conditional formatting and styling to the cells and rows, or to change rendering and colors.
Solution
There are several approaches you can take depending on the goals and situation that you have:
- OnCellRender and OnRowRender Events - fine grained control over the styling of a particular cell or row
- Cell Template - control over the contents of the cells
- Row Template - change the entire contents of the row
- CSS Only Approach - override built-in CSS rules with your own without conditions or custom themes
These approaches, including the OnCellRender and OnRowRender events, are applicable for the TreeList as well.
OnCellRender and OnRowRender Events
To customize the formatting of the cells you can use the OnCellRender event, exposed for the Grid Column.
To customize the formatting of the entire row, use the OnRowRender event for the Grid.
These events provide you with the data item and cell value, and let you set a custom class to the corresponding element, so you can cascade the needed CSS rules through it.
@* Conditional styling/formatting for a cell and row *@
<style>
.highlightCellBackGround {
background-color: lightyellow;
}
.negativeValuesRowFormatting {
color: red;
}
.positiveValuesRowFormatting {
color: green;
}
</style>
<TelerikGrid Data="@GridData"
Height="400px"
Pageable="true"
Sortable="true"
FilterMode="Telerik.Blazor.GridFilterMode.FilterRow"
Resizable="true"
Reorderable="true"
OnRowRender="@OnRowRenderHandler">
<GridColumns>
<GridColumn Field="@(nameof(AccountingData.ClientId))" Width="120px" />
<GridColumn Field="@(nameof(AccountingData.ClientName))" Title="Client Name" Groupable="false" />
<GridColumn Field="@(nameof(AccountingData.DateOfLastReport))" Title="Date Of Last Report" />
<GridColumn Field="@(nameof(AccountingData.NetBalance))"
Title="Net Balance"
OnCellRender="@OnCellRenderHandler" />
</GridColumns>
</TelerikGrid>
@code {
void OnCellRenderHandler(GridCellRenderEventArgs args)
{
args.Class = "highlightCellBackGround";
}
void OnRowRenderHandler(GridRowRenderEventArgs args)
{
AccountingData item = args.Item as AccountingData;
args.Class = item.NetBalance > 0 ? "positiveValuesRowFormatting" : "negativeValuesRowFormatting";
}
public List<AccountingData> GridData { get; set; }
protected override void OnInitialized()
{
GridData = new List<AccountingData>();
GenerateAccountingData();
base.OnInitialized();
}
public void GenerateAccountingData()
{
Random rand = new Random();
for (int i = 0; i < 50; i++)
{
GridData.Add(new AccountingData()
{
ClientId = i,
ClientName = $"Client {i}",
DateOfLastReport = DateTime.Today.AddDays(-i),
NetBalance = rand.Next(-15000, 25000)
});
}
}
public class AccountingData
{
public int ClientId { get; set; }
public string ClientName { get; set; }
public DateTime DateOfLastReport { get; set; }
public int NetBalance { get; set; }
}
}
Cell Template
You can use a particular column's cell template to render conditional markup inside its cell. In this case you will need some CSS to make your element take up the entire size of the cell so the default padding from the grid does not leave some of the original background visible.
<style>
/* remove the default cell padding to remove traces of the original background */
.k-grid-table .k-table-td {
padding: 0;
/*height: 40px;*/ /*you may want to set height to the cells so the height:100% to the child div works better*/
}
.k-grid-table .k-table-td .cell-padding {
height: 100%;
padding: 5px; /* apply the desired cell padding here */
}
/* the custom background - in this example, on every third element*/
.k-grid-table .k-table-td .special-background {
background: yellow;
}
</style>
<TelerikGrid Data="@MyData" Height="500px">
<GridColumns>
<GridColumn Field="@(nameof(SampleData.ID))" Title="Photo">
<Template>
@{
var employee = context as SampleData;
// add the class (or inline style) that sets special background based on the desired condition
<div class="@( employee.ID % 3 == 0 ? "special-background cell-padding" : "cell-padding" )">@employee.ID</div>
}
</Template>
</GridColumn>
<GridColumn Field="@(nameof(SampleData.Name))" Title="Employee Name">
</GridColumn>
<GridColumn Field="HireDate" Title="Hire Date - Default string">
</GridColumn>
<GridColumn Field="HireDate" Title="Hire Date - Custom string">
<Template>
@((context as SampleData).HireDate.ToString("dd MMM yyyy"))
</Template>
</GridColumn>
</GridColumns>
</TelerikGrid>
@code {
public class SampleData
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}
public IEnumerable<SampleData> MyData = Enumerable.Range(1, 50).Select(x => new SampleData
{
ID = x,
Name = "name " + x,
HireDate = DateTime.Now.AddDays(-x)
});
}
Row Template
You can fully control the row rendering through a row template and apply the classes or inline rules you require to individual cells, or to all cells. Review the requirements and limitations of the row templates and if they suit you needs.
<style>
.yellow-cell-bg {
background: yellow;
}
</style>
<TelerikGrid Data=@MyData Height="500px">
<RowTemplate>
@{
SampleData currRowData = context as SampleData;
// to style the entire row, you can use the same class for all cells, or their style attribute
// to style individual cells - either use their style attribute, or apply a conditional class only to them
<td style="@GetConditionalCellStyle(currRowData)" class="@GetConditionalCellClass(currRowData)">
<img class="rounded-circle" src="@($"/images/{currRowData.ID}.jpg")" alt="employee photo" />
<strong>@currRowData.Name</strong>
</td>
<td class="@GetConditionalCellClass(currRowData)">
Hired on: @(String.Format("{0:dd MMM yyyy}", currRowData.HireDate))
</td>
}
</RowTemplate>
<GridColumns>
<GridColumn Field=@nameof(SampleData.Name) Title="Employee Name" />
<GridColumn Field=@nameof(SampleData.HireDate) Title="Hire Date" />
</GridColumns>
</TelerikGrid>
@code {
string GetConditionalCellStyle(SampleData rowData)
{
if (rowData.Name.Contains("5"))
{
return "background-color: green;";
}
return string.Empty;
}
string GetConditionalCellClass(SampleData rowData)
{
if(rowData.ID % 3 == 0)
{
return "yellow-cell-bg";
}
return string.Empty;
}
public class SampleData
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime HireDate { get; set; }
}
public IEnumerable<SampleData> MyData = Enumerable.Range(1, 50).Select(x => new SampleData
{
ID = x,
Name = "name " + x,
HireDate = DateTime.Now.AddDays(-x)
});
}
CSS Only Approach
If you want to change the default row and alternating row backgrounds to match your app styles, without conditional logic being required for that, you only need some CSS that you can find in example below.
<style>
.custom-row-colors .k-grid-table .k-master-row {
background-color: red;
}
.custom-row-colors .k-grid-table .k-table-row.k-master-row:hover {
background-color: pink;
}
.custom-row-colors .k-grid-table .k-master-row.k-alt {
background-color: green;
}
.custom-row-colors .k-grid-table .k-master-row.k-alt:hover {
background-color: cyan;
}
</style>
<TelerikGrid Data="@MyData" Height="400px" Class="custom-row-colors"
Pageable="true" Sortable="true" Groupable="true"
FilterMode="Telerik.Blazor.GridFilterMode.FilterRow"
Resizable="true" Reorderable="true">
<GridColumns>
<GridColumn Field="@(nameof(SampleData.Id))" Width="120px" />
<GridColumn Field="@(nameof(SampleData.Name))" Title="Employee Name" Groupable="false" />
<GridColumn Field="@(nameof(SampleData.Team))" Title="Team" />
<GridColumn Field="@(nameof(SampleData.HireDate))" Title="Hire Date" />
</GridColumns>
</TelerikGrid>
@code {
public IEnumerable<SampleData> MyData = Enumerable.Range(1, 30).Select(x => new SampleData
{
Id = x,
Name = "name " + x,
Team = "team " + x % 5,
HireDate = DateTime.Now.AddDays(-x).Date
});
public class SampleData
{
public int Id { get; set; }
public string Name { get; set; }
public string Team { get; set; }
public DateTime HireDate { get; set; }
}
}