Estilo condicional de cuadrícula de árbol Angular
Si necesita proporcionar algún estilo personalizado en el componente IgxTreeGrid, puede hacerlo a nivel de fila o de celda.
Estilo de fila condicional de cuadrícula de árbol
El componente IgxTreeGrid de Ignite UI for Angular proporciona dos formas de aplicar estilos condicionales a las filas en función de reglas personalizadas.
By setting rowClasses
input on the IgxTreeGrid component;
Al configurar la entrada rowStyles
en el componente IgxTreeGrid;
Más adelante en este tema los cubriremos con más detalle.
Usando clases de fila
Puede diseñar condicionalmente las filas de IgxTreeGrid configurando la entrada rowClasses
y definiendo reglas personalizadas.
<igx-tree-grid #treeGrid [data ]="data" [height ]="'600px'" [width ]="'100%'" [rowClasses ]="rowClasses" >
...
</igx-tree-grid >
html
La entrada rowClasses
acepta un objeto literal, que contiene pares clave-valor, donde la clave es el nombre de la clase CSS, mientras que el valor es una función de devolución de llamada que devuelve un valor booleano o booleano.
public rowClasses = {
activeRow : this .activeRowCondition
};
public activeRowCondition = (row: RowType ) => this .grid?.navigation.activeNode?.row === row.index;
typescript
::ng-deep {
.activeRow {
border: 2px solid #fc81b8 ;
border-left : 3px solid #e41c77 ;
}
}
scss
Utilice::ng-deep
o ViewEncapsulation.None
para forzar los estilos personalizados hacia abajo a través del componente actual y sus elementos secundarios.
Manifestación
import { Component, OnInit, ViewChild } from '@angular/core' ;
import { IgxTreeGridComponent, RowType, IgxColumnComponent } from 'igniteui-angular' ;
import { generateEmployeeFlatData, IEmployee } from '../data/employees-flat' ;
import { IgxPreventDocumentScrollDirective } from '../directives/prevent-scroll.directive' ;
import { NgFor } from '@angular/common' ;
@Component ({
selector : 'app-tree-grid-row-classes-sample' ,
styleUrls : ['tree-grid-rowClasses.component.scss' ],
templateUrl : 'tree-grid-rowClasses.component.html' ,
imports : [IgxTreeGridComponent, IgxPreventDocumentScrollDirective, NgFor, IgxColumnComponent]
})
export class TreeGridRowClassesComponent implements OnInit {
@ViewChild ('treeGrid' , { static : true }) public treeGrid1: IgxTreeGridComponent;
public data: IEmployee[];
public columns: any [];
public ngOnInit(): void {
this .data = generateEmployeeFlatData();
this .columns = [
{ field : 'Name' , label : 'Full Name' , resizable : true , filterable : true , editable : true , dataType : 'string' },
{ field : 'Age' , label : 'Age' , resizable : false , filterable : false , editable : true , dataType : 'number' },
{ field : 'Title' , label : 'Title' , resizable : true , filterable : true , editable : true , dataType : 'string' },
{ field : 'HireDate' , label : 'Hire Date' , resizable : true , filterable : true , editable : true , dataType : 'date' }
];
}
public activeRowCondition = (row: RowType ) => this .treeGrid1?.navigation.activeNode?.row === row.index;
public rowClasses = {
activeRow : this .activeRowCondition
};
public handleChange ( ) {
requestAnimationFrame(() => {
this .treeGrid1.pipeTrigger++;
this .treeGrid1.notifyChanges();
});
}
public handleLeftClick (args ) {
args.event.preventDefault();
this .treeGrid1.navigation.setActiveNode({ row : args.cell.row.index, column : args.cell.column.visibleIndex });
}
}
ts コピー <div class ="grid__wrapper" >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #treeGrid [data ]="data" primaryKey ="ID" foreignKey ="ParentID" [rowClasses ]="rowClasses"
width ="100%" height ="550px" [rowEditable ] = "true" [moving ]="true" (contextMenu )="handleLeftClick($event)" (activeNodeChange )="handleChange()" >
<igx-column *ngFor ="let c of columns"
[editable ] ="c.editable"
[field ]="c.field"
[dataType ]="c.dataType"
[header ]="c.label"
[resizable ]="c.resizable"
[sortable ]="c.sortable"
[filterable ]="c.filterable"
>
</igx-column >
</igx-tree-grid >
</div >
html コピー .grid__wrapper {
margin : 16px ;
}
::ng-deep {
.activeRow {
border: 1px solid #fc81b8 ;
border-left : 3px solid #e41c77 ;
}
.toggle-section {
width : 300px ;
height : 100px ;
background-color : white;
}
}
scss コピー
¿Te gusta esta muestra? Obtenga acceso a nuestro kit de herramientas de Ignite UI for Angular completo y comience a crear sus propias aplicaciones en minutos. Descárgalo gratis.
Usando estilos de fila
Las columnas ahora exponen la propiedad rowStyles
que permite aplicar estilos condicionales a las filas de datos. Similar a rowClasses
acepta un objeto literal donde las claves son propiedades de estilo y los valores son expresiones para evaluación. Además, puedes aplicar un peinado regular (sin condiciones).
La firma de devolución de llamada tanto para rowStyles
como para rowClasses
es:
(row: RowType) => boolean
ts
Definamos nuestros estilos:
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
};
typescript
<igx-tree-grid #treeGrid [data ]="data" [moving ]="true" primaryKey ="ID" foreignKey ="ParentID"
width ="100%" height ="550px" [rowStyles ]="rowStyles" >
...
</igx-tree-grid >
html
Manifestación
import { Component, OnInit, ViewChild } from '@angular/core' ;
import { IgxTreeGridComponent, RowType, IgxColumnComponent } from 'igniteui-angular' ;
import { generateEmployeeFlatData, IEmployee } from '../data/employees-flat' ;
import { IgxPreventDocumentScrollDirective } from '../directives/prevent-scroll.directive' ;
import { NgFor } from '@angular/common' ;
@Component ({
selector : 'app-tree-grid-row-styles-sample' ,
styleUrls : ['tree-grid-rowStyle.component.scss' ],
templateUrl : 'tree-grid-rowStyle.component.html' ,
imports : [IgxTreeGridComponent, IgxPreventDocumentScrollDirective, NgFor, IgxColumnComponent]
})
export class TreeGridRowStylesComponent implements OnInit {
@ViewChild ('treeGrid' , { static : true }) public treeGrid1: IgxTreeGridComponent;
public data: IEmployee[];
public columns: any [];
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
};
public ngOnInit(): void {
this .data = generateEmployeeFlatData();
this .columns = [
{ field : 'Name' , label : 'Full Name' , resizable : true , filterable : true , editable : true , dataType : 'string' },
{ field : 'Age' , label : 'Age' , resizable : false , filterable : false , editable : true , dataType : 'number' },
{ field : 'Title' , label : 'Title' , resizable : true , filterable : true , editable : true , dataType : 'string' },
{ field : 'HireDate' , label : 'Hire Date' , resizable : true , filterable : true , editable : true , dataType : 'date' }
];
}
}
ts コピー <div class ="grid__wrapper" >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #treeGrid [data ]="data" [moving ]="true" primaryKey ="ID" foreignKey ="ParentID"
width ="100%"
height ="550px"
[rowStyles ] = "rowStyles"
>
<igx-column *ngFor ="let c of columns"
[editable ] ="c.editable"
[field ]="c.field"
[dataType ]="c.dataType"
[header ]="c.label"
[resizable ]="c.resizable"
[sortable ]="c.sortable"
[filterable ]="c.filterable"
>
</igx-column >
</igx-tree-grid >
</div >
html コピー .grid__wrapper {
margin : 16px ;
}
scss コピー
Estilo de celda condicional de cuadrícula de árbol
Descripción general
El componente IgxTreeGrid de Ignite UI for Angular proporciona dos formas de aplicar estilos condicionales a las celdas en función de reglas personalizadas.
Configurando las cellClasses
de entrada IgxColumnComponent
en un objeto literal que contiene pares clave-valor. La clave es el nombre de la clase CSS, mientras que el valor es una función de devolución de llamada que devuelve un valor booleano o booleano. El resultado es una cómoda colocación del material en la celda.
public beatsPerMinuteClasses = {
downFont : this .downFontCondition,
upFont : this .upFontCondition
};
...
private downFontCondition = (rowData: any , columnKey : any ): boolean => {
return rowData[columnKey] <= 95 ;
}
ts
.upFont {
color : red;
}
.downFont {
color : green;
}
scss
Usando clases de celdas
Puede diseñar condicionalmente las celdas IgxTreeGrid configurando la entrada IgxColumnComponent
cellClasses
y definiendo reglas personalizadas.
<igx-column field ="UnitPrice" header ="Unit Price" [dataType ]="'currency'" [pipeArgs ]="formatOptions" [cellClasses ]="priceClasses" > </igx-column >
html
La entrada cellClasses
acepta un objeto literal, que contiene pares clave-valor, donde la clave es el nombre de la clase CSS, mientras que el valor es una función de devolución de llamada que devuelve un valor booleano o booleano.
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
};
typescript
::ng-deep {
.upPrice {
color: red;
}
.downPrice {
color : green;
}
}
scss
Utilice::ng-deep
o ViewEncapsulation.None
para forzar los estilos personalizados hacia abajo a través del componente actual y sus elementos secundarios.
Manifestación
import { Component, OnInit } from '@angular/core' ;
import { ORDERS_DATA } from '../data/orders' ;
import { IgxTreeGridComponent, IgxColumnComponent, IgxCellTemplateDirective } from 'igniteui-angular' ;
import { IgxPreventDocumentScrollDirective } from '../directives/prevent-scroll.directive' ;
import { NgIf } from '@angular/common' ;
@Component ({
selector : 'app-tree-grid-conditional-cell-style-sample' ,
styleUrls : ['./tree-grid-conditional-cell-style-sample.component.scss' ],
templateUrl : './tree-grid-conditional-cell-style-sample.component.html' ,
imports : [IgxTreeGridComponent, IgxPreventDocumentScrollDirective, IgxColumnComponent, IgxCellTemplateDirective, NgIf]
})
export class TreeGridConditionalCellStyleComponent implements OnInit {
public data: any [];
public allergenItems = ['Frozen Shrimps' , 'Wild Salmon Fillets' , 'Fresh Cheese' , 'Skimmed Milk 1L' , 'Butter' ];
public options = {
digitsInfo : '1.2-2' ,
currencyCode : 'USD'
};
public formatOptions = this .options;
public ngOnInit ( ) {
this .data = ORDERS_DATA;
}
public formatDate (val: Date ) {
return new Intl .DateTimeFormat('en-US' ).format(val);
}
private upPriceCondition = (rowData: any , columnKey : any ): boolean => rowData[columnKey] > 5 ;
private downPriceCondition = (rowData: any , columnKey : any ): boolean => rowData[columnKey] <= 5 ;
private allergenCondition = (rowData: any , columnKey : any ): boolean => this .allergenItems.indexOf(rowData[columnKey]) >= 0 ;
public priceClasses = {
downPrice : this .downPriceCondition,
upPrice : this .upPriceCondition
};
public allergenClasses = {
'allergens allergensFont' : this .allergenCondition
};
}
ts コピー <div class ="grid__wrapper" >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #grid1 [data ]="data" height ="530px" width ="100%" [autoGenerate ]="false"
primaryKey ="ID" foreignKey ="ParentID" >
<igx-column field ="ID" header ="Order ID" >
</igx-column >
<igx-column field ="Name" header ="Order Product" [cellClasses ] = "allergenClasses" >
</igx-column >
<igx-column field ="Category" header ="Category" >
</igx-column >
<igx-column field ="Units" header ="Units" [dataType ]="'number'" >
</igx-column >
<igx-column field ="UnitPrice" header ="Unit Price" [dataType ]="'currency'" [pipeArgs ]="formatOptions" [cellClasses ] = "priceClasses" >
</igx-column >
<igx-column field ="Price" header ="Price" [dataType ]="'currency'" [pipeArgs ]="formatOptions" >
</igx-column >
<igx-column field ="OrderDate" header ="Order Date" [dataType ]="'date'" [formatter ]="formatDate" >
</igx-column >
<igx-column field ="Delivered" header ="Delivered" [sortable ]="true" [disableHiding ]="true" [dataType ]="'boolean'" >
<ng-template igxCell let-cell ="cell" let-val >
<img *ngIf ="val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/active.png" title ="Delivered" alt ="Delivered" />
<img *ngIf ="!val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/expired.png" title ="Undelivered" alt ="Undelivered" />
</ng-template >
</igx-column >
</igx-tree-grid >
<span id ="message" > May contain allergens.</span >
</div >
html コピー .grid__wrapper {
margin : 16px ;
}
:host ::ng-deep {
$primary-color-green : green;
$primary-color-red : red;
$primary-color-blue : royalblue;
$margin-right-images : 5px ;
$images-font-size : 1.5em ;
$images-font-weight : bold;
.upPrice {
color : $primary-color-red ;
}
.downPrice {
color : $primary-color-green ;
}
.allergensFont {
color : $primary-color-blue ;
}
.contentStyle {
font-size : $images-font-size ;
font-weight : $images-font-weight ;
margin-right : $margin-right-images ;
}
.star {
@extend .contentStyle;
content : "*" ;
}
.allergens :after {
@extend .star;
font-weight : normal;
color : $primary-color-blue ;
vertical-align : top;
margin-left : 2px ;
}
#message :before {
@extend .star;
font-weight : lighter;
color : $primary-color-blue ;
vertical-align : top;
margin-right : 2px ;
}
#message {
color : $primary-color-blue ;
font-style : italic;
font-size : 0.75rem ;
}
}
scss コピー
Utilizando la entrada cellStyles
IgxColumnComponent
, que acepta un objeto literal donde las claves son propiedades de estilo y los valores son expresiones para evaluación.
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'
};
ts
La firma de devolución de llamada para cellStyles
y cellClasses
ahora se cambia a:
(rowData: any , columnKey : string , cellValue : any , rowIndex : number ) => boolean
ts
Usando estilos de celda
Las columnas ahora exponen la propiedad cellStyles
que permite aplicar estilos condicionales a las celdas de las columnas. Al igual que cellClasses
acepta un objeto literal donde las claves son propiedades de estilo y los valores son expresiones para evaluación. Además, puedes aplicar el peinado habitual con facilidad (sin condiciones).
En el ejemplo anterior hemos creado:
Dos estilos diferentes que se aplicarán según el índice de la columna.
También cambiará el text color
según las filas pares/impares.
La firma de devolución de llamada para ambos cellStyles
es:
(rowData: any , columnKey : string , cellValue : any , rowIndex : number ) => boolean
ts
Definamos nuestros estilos:
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'
};
typescript
En ngOnInit
agregaremos la configuración cellStyles
para cada columna de la colección columns
predefinidas, que se utiliza para crear las columnas IgxTreeGrid dinámicamente.
public ngOnInit ( ) {
this .data = ORDERS_DATA;
this .columns = [
{ field : 'ID' },
{ field : 'Name' },
{ field : 'UnitPrice' },
{ field : 'OrderDate' }
];
this .applyCSS();
}
ts
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();
}
ts
//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 >
html
Definir una animación popin
@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;
}
}
scss
Manifestación
import { Component, OnInit, ViewChild } from '@angular/core' ;
import { IgxColumnComponent, IgxTreeGridComponent, IgxInputGroupComponent, IgxInputDirective, IgxHintDirective, IgxButtonDirective } from 'igniteui-angular' ;
import { ORDERS_DATA } from '../data/orders' ;
import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive' ;
import { NgFor, JsonPipe } from '@angular/common' ;
@Component ({
selector : 'app-grid-conditional-cell-style-2' ,
styleUrls : ['./tree-grid-conditional-cell-style-2.component.scss' ],
templateUrl : './tree-grid-conditional-cell-style-2.component.html' ,
imports : [IgxInputGroupComponent, IgxInputDirective, IgxHintDirective, IgxButtonDirective, IgxTreeGridComponent, IgxPreventDocumentScrollDirective, NgFor, IgxColumnComponent, JsonPipe]
})
export class TreeGridConditionalCellStyle2Component implements OnInit {
@ViewChild ('grid1' , { read : IgxTreeGridComponent, static : true })
public grid1: IgxTreeGridComponent;
public data: any [];
public columns: any [];
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'
};
public ngOnInit ( ) {
this .data = ORDERS_DATA;
this .columns = [
{ field : 'ID' },
{ field : 'Name' , header : 'Order Product' },
{ field : 'UnitPrice' , header : 'Unit Price' },
{ field : 'OrderDate' , header : 'Order Date' }
];
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();
}
public formatCurrency (value: number ) {
return `$${value.toFixed(2 )} ` ;
}
public formatDate (value ) {
return new Intl .DateTimeFormat('en-US' ).format(value);
}
public init (column: IgxColumnComponent ) {
console .log(column);
switch (column.field) {
case 'UnitPrice' :
column.formatter = this .formatCurrency;
break ;
case 'OrderDate' :
column.formatter = this .formatDate;
break ;
default :
return ;
}
}
}
ts コピー <div class ="grid__wrapper" >
<div >
<igx-input-group type ="border" >
<textarea style ="font-family: monospace;" #userCSS igxInput cols ="15" rows ="5" > {{ oddColStyles | json }}</textarea >
<igx-hint > Note: You cannot use the callback functionality here</igx-hint >
</igx-input-group >
<button igxButton ="outlined" (click )="updateCSS(userCSS.value)" > Apply new styles</button >
</div >
<igx-tree-grid [igxPreventDocumentScroll ]="true"
#grid1 [data ]="data"
primaryKey ="ID" foreignKey ="ParentID"
height ="350px"
(columnInit )="init($event)" >
<igx-column *ngFor ="let c of columns"
[field ]="c.field"
[header ]="c.header"
[cellStyles ]="c.cellStyles" >
</igx-column >
</igx-tree-grid >
</div >
html コピー .grid__wrapper {
margin : 0 auto;
padding : 16px ;
transition-timing-function : cubic-bezier(0.455 , 0.03 , 0.515 , 0.955 );
igx-input -group {
width : 100% ;
}
igx-tree-grid {
margin-top : 25px ;
}
}
@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;
}
}
scss コピー
Problemas y limitaciones conocidos
Si hay celdas enlazadas a la misma condición (de diferentes columnas) y una celda se actualiza, las demás celdas no se actualizarán en función del nuevo valor, si se cumple la condición. Se debe realizar una verificación de tubería para aplicar los cambios al resto de las celdas. En el ejemplo siguiente se muestra cómo hacerlo con un spread operator(...)
evento on onCellEdit
. Esto copiará el objeto original con una nueva instancia y hará que se dispare la tubería pura.
public backgroundClasses = {
myBackground : (rowData: any , columnKey: string ) => {
return rowData.Col2 < 10 ;
}
};
...
editDone (evt ) {
this .backgroundClasses = {...this.backgroundClasses};
}
ts
<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 >
html
Referencias de API
Recursos adicionales
Nuestra comunidad es activa y siempre da la bienvenida a nuevas ideas.