Angular Tree Grid Conditional Styling

    If you need to provide any custom styling in the IgxTreeGrid component, you can do it on either row or cell level.

    Tree Grid Conditional Row Styling

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

    • By setting rowClasses input on the IgxTreeGrid component;
    • By setting rowStyles input on the IgxTreeGrid component;

    Further in this topic wi will cover both of them in more details.

    Using rowClasses

    You can conditionally style the IgxTreeGrid rows by setting the rowClasses input and define custom rules.

    <!-- sample.component.html -->
    <igx-tree-grid #treeGrid [data]="data" [height]="'600px'" [width]="'100%'" [rowClasses]="rowClasses">
        ...
    </igx-tree-grid>
    

    The rowClasses 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
    
    public rowClasses = {
        activeRow: this.activeRowCondition
    };
    
    public activeRowCondition = (row: RowType) => this.grid?.navigation.activeNode?.row === row.index;
    
    // sample.component.scss
    
    ::ng-deep {
     .activeRow {
        border: 2px solid #fc81b8;
        border-left: 3px solid #e41c77;
     }
    }
    

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

    Demo

    Using rowStyles

    Columns now expose the rowStyles property which allows conditional styling of the data rows. Similar to rowClasses it accepts an object literal where the keys are style properties and the values are expressions for evaluation. Also, you can apply regular styling (without any conditions).

    The callback signature for both rowStyles and rowClasses is:

    (row: RowType) => boolean
    

    Let's define our styles:

    // component.ts
    public background = (row: RowType) => row.data['Title'] === 'CEO' ? '#6c757d' :
        row.data['Title'].includes('President') ? '#adb5bd' :
        row.data['Title'].includes('Director') ?  '#ced4da' :
        row.data['Title'].includes('Manager') ? '#dee2e6' :
        row.data['Title'].includes('Lead') ? '#e9ecef' :
        row.data['Title'].includes('Senior') ? '#f8f9fa' : null;
    
    public rowStyles = {
        background: this.background,
        'border-left': (row: RowType) => row.data['Title'] === 'CEO' || row.data['Title'].includes('President') ?
            '2px solid' : null,
        'border-color': (row: RowType) => row.data['Title'] === 'CEO' ? '#495057' : null,
        color: (row: RowType) => row.data['Title'] === 'CEO' ? '#fff' : null
    };
    
    <!-- sample.component.html -->
    <igx-tree-grid #treeGrid [data]="data" [moving]="true" primaryKey="ID" foreignKey="ParentID"
            width="100%" height="550px" [rowStyles]="rowStyles">
        ...
    </igx-tree-grid>
    

    Demo

    Tree Grid Conditional Cell Styling

    Overview

    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;
    }
    

    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]="'currency'" [pipeArgs]="formatOptions" [cellClasses]="priceClasses"></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] > 5;
    }
    
    private downPriceCondition = (rowData: any, columnKey: any): boolean => {
        return rowData[columnKey] <= 5;
    }
    
    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.

    Demo

    • 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
    

    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 = ORDERS_DATA;
         this.columns = [
            { field: 'ID' },
            { field: 'Name' },
            { field: 'UnitPrice' },
            { field: 'OrderDate' }
        ];
    
        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-tree-grid
        #grid1 [data]="data"
        primaryKey="ID" foreignKey="ParentID"
        height="350px">
        <igx-column *ngFor="let c of columns"
            [field]="c.field"
            [header]="c.header"
            [cellStyles]="c.cellStyles">
        </igx-column>
    </igx-tree-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;
        }
    }
    

    Demo

    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-tree-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>
    </igx-tree-grid>
    

    API References

    Additional Resources

    Our community is active and always welcoming to new ideas.