Angular Tree Grid 条件付きスタイル設定
IgxTreeGrid コンポーネントでカスタム スタイルを提供する必要がある場合は、行レベルまたはセル レベルで行うことができます。
Tree Grid 条件付き行のスタイル設定
Ignite UI for Angular の IgxTreeGrid コンポーネントは、カスタム ルールに基づいて行の条件付きスタイル設定を作成する次の 2 つの方法を提供します:
さらにこのトピックでは、両方について詳しく説明します。
rowClasses の使用
rowClasses
入力を設定し、カスタム ルールを定義することで、IgxTreeGrid 行のスタイルを条件付きで設定できます。
<igx-tree-grid #treeGrid [data]="data" [height]="'600px'" [width]="'100%'" [rowClasses]="rowClasses">
...
</igx-tree-grid>
html
rowClasses
入力は、キー値のペアを含むオブジェクト リテラルを受け入れます。ここで、キーは CSS クラスの名前であり、値はブール値またはブール値を返すコールバック関数となります。
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
::ng-deep
または ViewEncapsulation.None
を使用してカスタム スタイルを現在のコンポーネントとその子コンポーネントに適用します。
デモ
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from "./app.component";
import { TreeGridRowClassesComponent } from "./tree-grid-rowClasses-sample/tree-grid-rowClasses.component";
import { IgxTreeGridModule } from "igniteui-angular";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
TreeGridRowClassesComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { IgxTreeGridComponent, RowType } from 'igniteui-angular';
import { generateEmployeeFlatData, IEmployee } from '../data/employees-flat';
@Component({
selector: 'app-tree-grid-row-classes-sample',
styleUrls: ['tree-grid-rowClasses.component.scss'],
templateUrl: 'tree-grid-rowClasses.component.html'
})
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
このサンプルが気に入りましたか? 完全な Ignite UI for Angularツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
rowStyles の使用
列は、データ行の条件付きスタイル設定を可能にする rowStyles
プロパティを公開するようになりました。rowClasses
と同様、キーがスタイル プロパティであり、値が評価用の式であるオブジェクト リテラルを受け取ります。また、通常のスタイル設定 (条件なし) を適用することもできます。
rowStyles
と rowClasses
の両方のコールバック署名は次のとおりです:
(row: RowType) => boolean
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
};
typescript
<igx-tree-grid #treeGrid [data]="data" [moving]="true" primaryKey="ID" foreignKey="ParentID"
width="100%" height="550px" [rowStyles]="rowStyles">
...
</igx-tree-grid>
html
デモ
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from "./app.component";
import { TreeGridRowStylesComponent } from "./tree-grid-rowStyles-sample/tree-grid-rowStyle.component";
import { IgxTreeGridModule } from "igniteui-angular";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
TreeGridRowStylesComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { IgxTreeGridComponent, RowType } from 'igniteui-angular';
import { generateEmployeeFlatData, IEmployee } from '../data/employees-flat';
@Component({
selector: 'app-tree-grid-row-styles-sample',
styleUrls: ['tree-grid-rowStyle.component.scss'],
templateUrl: 'tree-grid-rowStyle.component.html'
})
export class TreeGridRowStylesComponent implements OnInit {
@ViewChild('treeGrid', { static: true }) public treeGrid1: IgxTreeGridComponent;
public data: IEmployee[];
public columns: any[];
public background = (row: RowType) => row.data.data['Title'] === 'CEO' ? '#6c757d' :
row.data.data['Title'].includes('President') ? '#adb5bd' : row.data.data['Title'].includes('Director') ? '#ced4da' :
row.data.data['Title'].includes('Manager') ? '#dee2e6' :
row.data.data['Title'].includes('Lead') ? '#e9ecef' :
row.data.data['Title'].includes('Senior') ? '#f8f9fa' : null;
public rowStyles = {
background: this.background,
'border-left': (row: RowType) => row.data.data['Title'] === 'CEO' || row.data.data['Title'].includes('President') ?
'2px solid' : null,
'border-color': (row: RowType) => row.data.data['Title'] === 'CEO' ? '#495057' : null,
color: (row: RowType) => row.data.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
Tree Grid 条件付きセル スタイル設定
概要
Ignite UI for Angular の IgxTreeGrid コンポーネントは、カスタム条件に基づいて 2 通りの条件付きセルのスタイル設定をサポートします。
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
cellClasses の使用
IgxColumnComponent
cellClasses
入力を設定してカスタム条件を定義することにより、IgxTreeGrid の条件付きセルのスタイルを設定できます。
<igx-column field="UnitPrice" header="Unit Price" [dataType]="'currency'" [pipeArgs]="formatOptions" [cellClasses]="priceClasses"></igx-column>
html
cellClasses
入力は、キーと値のペアを含むオブジェクト リテラルを受け取ります。キーは CSS クラスの名前です。値はブール値を返すコールバック関数またはブール値です。
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
::ng-deep
または ViewEncapsulation.None
を使用してカスタム スタイルを現在のコンポーネントとその子コンポーネントに適用します。
デモ
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from "./app.component";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
import { IgxTreeGridModule } from "igniteui-angular";
import { TreeGridConditionalCellStyleComponent } from "./tree-grid-conditional-cell-style-sample/tree-grid-conditional-cell-style-sample.component";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
TreeGridConditionalCellStyleComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, OnInit } from '@angular/core';
import { FOODS_DATA } from '../data/foods';
@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'
})
export class TreeGridConditionalCellStyleComponent implements OnInit {
public data: any[];
public allergenItems = ['Grandmas Boysenberry Spread', 'Mishi Kobe Niku', 'Carnarvon Tigers', 'Ikura'];
public ngOnInit() {
this.data = FOODS_DATA();
}
public formatDate(val: Date) {
return new Intl.DateTimeFormat('en-US').format(val);
}
private upPriceCondition = (rowData: any, columnKey: any): boolean => rowData[columnKey] > 25;
private downPriceCondition = (rowData: any, columnKey: any): boolean => rowData[columnKey] <= 25;
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="Product ID" [dataType]="'string'" >
</igx-column>
<igx-column field="Name" header="Product Name" [dataType]="'string'" [cellClasses] = "allergenClasses" >
</igx-column>
<igx-column field="UnitPrice" header="Unit Price" dataType="number" [cellClasses] = "priceClasses">
<ng-template igxCell let-cell="cell" let-val>
<span *ngIf="cell.row.data.UnitPrice === 0">-</span>
<span *ngIf="cell.row.data.UnitPrice !== 0">${{val}}</span>
</ng-template>
</igx-column>
<igx-column field="AddedDate" header="Added Date" [dataType]="'date'" [formatter]="formatDate">
</igx-column>
<igx-column field="Discontinued" header="Discontinued" [dataType]="'boolean'">
<ng-template igxCell let-cell="cell" let-val>
<span *ngIf="cell.row.data.UnitPrice === 0">-</span>
<img *ngIf="cell.row.data.UnitPrice !== 0 && val" src="https://www.infragistics.com/angular-demos-lob/assets/images/grid/active.png" title="Continued" alt="Continued" />
<img *ngIf="cell.row.data.UnitPrice !== 0 && !val" src="https://www.infragistics.com/angular-demos-lob/assets/images/grid/expired.png" title="Discontinued" alt="Discontinued" />
</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
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
cellStyles
と cellClasses
の両方のコールバック シグネチャが次のように変更されました。
(rowData: any, columnKey: string, cellValue: any, rowIndex: number) => boolean
ts
cellStyles の使用
列の cellStyles
プロパティを公開。列セルの条件付きスタイリングが可能になりました。cellClasses
と同様、キーがスタイル プロパティであり、値が評価用の式であるオブジェクト リテラルを受け取ります。また、通常のスタイリングを簡単に適用できます (条件なし)。
上記のサンプルで作成した項目:
- 列インデックスに基づいて適用される 2 つの異なるスタイル。
- また、偶数/奇数行に基づいて
テキストの色
を変更します。
両方の cellStyles
のコールバック署名は以下のとおりです。
(rowData: any, columnKey: string, cellValue: any, rowIndex: number) => boolean
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'
};
typescript
ngOnInit
で、IgxTreeGrid 列を動的に作成するために使用される事前定義 columns
コレクションの各列に cellStyles
構成を追加します。
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
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
デモ
import { NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { AppComponent } from "./app.component";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
import { IgxTreeGridModule } from "igniteui-angular";
import { TreeGridConditionalCellStyle2Component } from "./tree-grid/tree-grid-conditional-cell-style-2/tree-grid-conditional-cell-style-2.component";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
TreeGridConditionalCellStyle2Component
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { IgxTreeGridComponent } from 'igniteui-angular';
import { FOODS_DATA } from '../data/foods';
@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'
})
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 = FOODS_DATA();
this.columns = [
{ field: 'ID' },
{ field: 'Name' },
{ field: 'UnitPrice' },
{ field: 'AddedDate' }
];
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();
}
}
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">
<igx-column *ngFor="let c of columns"
[field]="c.field"
[header]="c.field"
[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
既知の問題と制限
- 他の列に同じ条件でバインドされたセルがある場合、その 1 つのセルが更新された際に条件が満たされて要る場合も他のセルが新しい値に基づいて更新されない問題。
残りのセルに変更を適用するには、パイプ チェックを実行する必要があります。以下の例は、
onCellEdit
イベントで spread operator(...)
を使用してチェックを実行する方法を示します。これにより、元のオブジェクトが新しいインスタンスでコピーされ、パイプのみ発生します。
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
API リファレンス
その他のリソース
コミュニティに参加して新しいアイデアをご提案ください。