Tree Grid Conditional Cell Styling

The IgxTreeGrid component in Ignite UI for Angular provides two ways to conditional styling of cells based on custom rules.

  • By setting the IgxColumnComponent input cellClasses to an object literal containing key-value pairs. The key is the name of the CSS class, while the value is either a callback function that returns a boolean, or boolean value. The result is a convenient material styling of the cell.
// component.ts file
public beatsPerMinuteClasses = {
    downFont: this.downFontCondition,
    upFont: this.upFontCondition
};
...

private downFontCondition = (rowData: any, columnKey: any): boolean => {
    return rowData[columnKey] <= 95;
}
// component.scss file
.upFont {
    color: red;
}

.downFont {
    color: green;
}

Demo with 'cellClasses'


  • By using the IgxColumnComponent input cellStyles which accepts an object literal where the keys are style properties and the values are expressions for evaluation.
public styles = {
    "background": "linear-gradient(180deg, #dd4c4c 0%, firebrick 100%)",
    "text-shadow": "1px 1px 2px rgba(25,25,25,.25)",
    "animation": "0.25s ease-in-out forwards alternate popin"
};

The callback signature for both cellStyles and cellClasses is now changed to:

(rowData: any, columnKey: string, cellValue: any, rowIndex: number) => boolean

Demo with 'cellStyles'


Overview

Using cellClasses

You can conditionally style the IgxTreeGrid cells by setting the IgxColumnComponent cellClasses input and define custom rules.

<!-- sample.component.html -->
<igx-column field="UnitPrice" header="Unit Price" [dataType]="'number'" [cellClasses] = "priceClasses">
    <ng-template igxCell let-cell="cell" let-val>
        <span *ngIf="cell.row.rowData.UnitPrice == 0">-</span>
        <span *ngIf="cell.row.rowData.UnitPrice != 0">${{val}}</span>
    </ng-template>
</igx-column>

The cellClasses input accepts an object literal, containing key-value pairs, where the key is the name of the CSS class, while the value is either a callback function that returns a boolean, or boolean value.

// sample.component.ts

private upPriceCondition = (rowData: any, columnKey: any): boolean => {
    return rowData[columnKey] > 25;
}

private downPriceCondition = (rowData: any, columnKey: any): boolean => {
    return rowData[columnKey] <= 25;
}

public priceClasses = {
    downPrice: this.downPriceCondition,
    upPrice: this.upPriceCondition
};
// sample.component.scss

::ng-deep {
    .upPrice {
        color: red;
    }

    .downPrice {
        color: green;
    }
}

Use ::ng-deep or ViewEncapsulation.None to force the custom styles down through the current component and its children.

Using cellStyles

Columns now expose the cellStyles property which allows conditional styling of the column cells. Similar to cellClasses it accepts an object literal where the keys are style properties and the values are expressions for evaluation. Also, you can apply regular styling with ease (without any conditions).

In the sample above we've created:

  • Two different styles that will be applied based on the column index.
  • You will also change the text color based on even/odd rows.

The callback signature for both cellStyles is:

(rowData: any, columnKey: string, cellValue: any, rowIndex: number) => boolean

Let's define our styles:

// component.ts
public oddColStyles = {
    background: "linear-gradient(to right, #b993d6, #8ca6db)",
    color: (rowData, coljey, cellValue, rowIndex) => rowIndex % 2 === 0 ? "white" : "gray",
    animation: "0.75s popin"
};

public evenColStyles = {
    background: "linear-gradient(to right, #8ca6db, #b993d6)",
    color: (rowData, coljey, cellValue, rowIndex) => rowIndex % 2 === 0 ? "gray" : "white",
    animation: "0.75s popin"
};

On ngOnInit we will add the cellStyles configuration for each column of the predefined columns collection, which is used to create the IgxTreeGrid columns dynamically.

// component.ts
public ngOnInit() {
    this.data = athletesData;
    this.columns = [
        { field: "Id" },
        { field: "Position" },
        { field: "Name" },
        { field: "AthleteNumber" },
        { field: "CountryName" }
    ];

    this.applyCSS();
}

public applyCSS() {
    this.columns.forEach((column, index) => {
        column.cellStyles = (index % 2 === 0 ? this.evenColStyles : this.oddColStyles);
    });
}

public updateCSS(css: string) {
    this.oddColStyles = {...this.oddColStyles, ...JSON.parse(css)};
    this.evenColStyles = {...this.evenColStyles, ...JSON.parse(css)};
    this.applyCSS();
}
// component.html
<igx-grid
    #grid1 [data]="data"
    primaryKey="ID"
    width="80%"
    height="300px">
    <igx-column *ngFor="let c of columns"
        [field]="c.field"
        [header]="c.field"
        [cellStyles]="c.cellStyles">
    </igx-column>
</igx-grid>

Define a popin animation

// component.scss
@keyframes popin {
    0% {
        opacity: 0.1;
        transform: scale(.75, .75);
        filter: blur(3px) invert(1);
    }

    50% {
        opacity: .5;
        filter: blur(1px);
    }

    100% {
        transform: scale(1, 1);
        opacity: 1;
        filter: none;
    }
}

Known issues and limitations

  • If there are cells bind to the same condition (from different columns) and one cell is updated, the other cells won't be updated based on the new value, if the condition is met. A pipe check should be performed in order to apply the changes to the rest of the cells. The example below shows how to do that with a spread operator ... on onCellEdit event. This will copy the original object with a new instance, and lead pure pipe to be fired.
public backgroundClasses = {
    myBackground: (rowData: any, columnKey: string) => {
        return rowData.Col2 < 10;
    }
};
...

editDone(evt) {
    this.backgroundClasses = {...this.backgroundClasses};
}
<igx-grid #grid1 [data]="data" height="500px" width="100%" (onCellEdit)="editDone($event)">
  <igx-column field="Col1" dataType="number" [cellClasses]="backgroundClasses"></igx-column>
  <igx-column field="Col2" dataType="number" [editable]="true" [cellClasses]="backgroundClasses"></igx-column>
  <igx-column field="Col3" header="Col3" dataType="string" [cellClasses]="backgroundClasses"></igx-column>
  ...

API References

Additional Resources

Our community is active and always welcoming to new ideas.