Angular Grid 列ピン固定
単一または複数の列を Angular UI グリッドの左端にピン固定できます。Ignite UI for Angular の列固定は、ユーザーが特定の列順序で列をロックすることを可能にし、Grid で水平スクロール時にロックされた列が常に表示されます。Material UI Grid には組み込みの列ピン固定 UI があり、Grid のツールバーで列の表示状態を変更できます。その他、カスタム UI を定義し、Column Pinning API を介して列のピン固定状態を変更できます。
Angular Grid 列ピン固定の例
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 { PinningToolbarSampleComponent } from "./grid/grid-sample-pinning/grid-toolbar-pinning.component";
import {
IgxGridModule,
IgxIconModule
} from "igniteui-angular";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
PinningToolbarSampleComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxGridModule,
IgxIconModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, ViewChild, ViewEncapsulation, OnInit } from '@angular/core';
import { IgxColumnComponent, IgxGridComponent } from 'igniteui-angular';
import { DATA } from '../../data/customers';
@Component({
encapsulation: ViewEncapsulation.None,
providers: [],
selector: 'app-grid-sample',
styleUrls: ['grid-toolbar-pinning.component.scss'],
templateUrl: 'grid-toolbar-pinning.component.html'
})
export class PinningToolbarSampleComponent implements OnInit{
@ViewChild('grid1', { static: true }) public grid1: IgxGridComponent;
public data: any[];
public columns: any[];
public ngOnInit(): void {
this.columns = [
{ field: 'CompanyName', header: 'Company Name', width: 300 },
{ field: 'ContactName', header: 'Contact Name', width: 200, pinned: true },
{ field: 'ContactTitle', header: 'Contact Title', width: 200, pinned: true },
{ field: 'Address', header: 'Address', width: 300 },
{ field: 'City', header: 'City', width: 120 },
{ field: 'Region', header: 'Region', width: 120 },
{ field: 'PostalCode', header: 'Postal Code', width: 150 },
{ field: 'Phone', header: 'Phone', width: 150 },
{ field: 'Fax', header: 'Fax', width: 150 }
];
this.data = DATA;
}
public toggleColumn(col: IgxColumnComponent) {
col.pinned ? col.unpin() : col.pin();
}
}
ts
<div class="grid__wrapper" style='width: 100%;'>
<igx-grid [igxPreventDocumentScroll]="true" #grid1 [data]="data" [width]="'100%'" [height]="'480px'">
<igx-grid-toolbar>
<igx-grid-toolbar-actions>
<igx-grid-toolbar-pinning></igx-grid-toolbar-pinning>
</igx-grid-toolbar-actions>
</igx-grid-toolbar>
<igx-column #col *ngFor="let c of columns" [field]="c.field" [header]="c.header" [width]="c.width" [pinned]='c.pinned'
[hidden]='c.hidden' [headerClasses]="'customHeaderSyle'">
</igx-column>
</igx-grid>
</div>
html
:host ::ng-deep .title {
width: 100%;
}
.grid__wrapper {
padding: 16px;
}
scss
このサンプルが気に入りましたか? 完全な Ignite UI for Angularツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
列固定 API
列ピン固定は、igx-column
の pinned
入力によって制御されます。ピン固定列は常に Grid の左側に描画され、Grid 本体のピン固定されていない列の水平スクロールで固定されます。
<igx-grid #grid1 [data]="data | async" [width]="700px" [autoGenerate]="false" (columnInit)="initColumns($event)"
(selected)="selectCell($event)">
<igx-column [field]="Name" [pinned]="true"></igx-column>
<igx-column [field]="AthleteNumber"></igx-column>
<igx-column [field]="TrackProgress"></igx-column>
<igx-paginator [perPage]="10">
</igx-paginator>
</igx-grid>
html
IgxGridComponent
の Grid の pinColumn
または unpinColumn
メソッドを使用してフィールド名によって列をピン固定またはピン固定解除できます。
this.grid.pinColumn('AthleteNumber');
this.grid.unpinColumn('Name');
typescript
両方のメソッドは操作に成功したかどうかを示すブール値を返します。よくある失敗の原因として列がすでにそのステートになっていることがあります。
列をピン固定すると、一番右に配置されたピン固定列の右にピン固定されます。ピン固定列の順序を変更するには、columnPin
イベントでイベント引数の insertAtIndex
プロパティを適切な位置インデックスに変更します。
<igx-grid #grid1 [data]="data | async" [autoGenerate]="true" (columnPin)="columnPinning($event)"></igx-grid>
html
public columnPinning(event) {
if (event.column.field === 'Name') {
event.insertAtIndex = 0;
}
}
typescript
ピン固定の位置
pinning
設定オプションを使用して、列のピン固定の位置を変更できます。列の位置を Start または End のいずれかに設定できます。End に設定すると、列がピン固定されていない列の後に、グリッドの最後にレンダリングされます。
ピン固定されていない列は水平にスクロールできますが、ピン固定された列は右側に固定されます。
<igx-grid [data]="data" [autoGenerate]="true" [pinning]="pinningConfig"></igx-grid>
html
public pinningConfig: IPinningConfig = { columns: ColumnPinningPosition.End };
typescript
デモ
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 { RightPinningSampleComponent } from "./grid/grid-sample-right-pinning/grid-right-pinning.component";
import {
IgxGridModule,
IgxTooltipModule,
IgxAvatarModule
} from "igniteui-angular";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
RightPinningSampleComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxGridModule,
IgxTooltipModule,
IgxAvatarModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, ViewChild, ViewEncapsulation, OnInit } from '@angular/core';
import { ColumnPinningPosition, IgxColumnComponent, IgxGridComponent, IPinningConfig } from 'igniteui-angular';
import { employeesData } from '../../data/employeesData';
import { athletesData } from '../../data/athletesData';
@Component({
encapsulation: ViewEncapsulation.None,
providers: [],
selector: 'app-grid-sample',
styleUrls: ['grid-right-pinning.component.scss'],
templateUrl: 'grid-right-pinning.component.html'
})
export class RightPinningSampleComponent implements OnInit{
@ViewChild('grid1', { static: true })
public grid1: IgxGridComponent;
public data: any[];
public employeesData: any[];
public columns: any[];
public pinningConfig: IPinningConfig = { columns: ColumnPinningPosition.End };
private _columnsPinned: boolean = true;
public ngOnInit(): void {
this.data = athletesData;
this.employeesData = employeesData;
let i = 0;
this.data.forEach((x) => {
x.FirstPlaces = Math.floor(Math.random() * Math.floor(3));
x.SecondPlaces = Math.floor(Math.random() * Math.floor(4));
x.ThirdPlaces = Math.floor(Math.random() * Math.floor(5));
x.RegistrationDate = this.generateReadableDate(x.Registered);
x.Birthday = this.generateReadableDate(this.employeesData[i].birthday);
x.Sponsor = this.employeesData[i].company;
x.Agent = this.employeesData[i].name;
x.AgentContact = this.employeesData[i].email;
x.AgentPhone = this.employeesData[i].work_phone;
i++;
});
}
public toggleColumn(col: IgxColumnComponent): void {
col.pinned ? col.unpin() : col.pin();
}
public get columnsPinned(): boolean {
return this._columnsPinned;
}
public set columnsPinned(pinned) {
this._columnsPinned = !this._columnsPinned;
}
private generateReadableDate(timestamp: string): Date {
let dateObj = new Date(timestamp);
if (isNaN(dateObj.getTime())) {
dateObj = new Date(timestamp.split(' ')[0]);
}
return dateObj;
}
}
ts
<div class="grid__wrapper">
<igx-grid #grid1 [data]="data" [width]="'100%'" [height]="'480px'" [pinning]="pinningConfig" [autoGenerate]="false">
<igx-grid-toolbar>
<igx-grid-toolbar-actions>
<igx-grid-toolbar-pinning></igx-grid-toolbar-pinning>
</igx-grid-toolbar-actions>
</igx-grid-toolbar>
<igx-column field="CountryName" header="Team" width="88">
<ng-template igxCell let-cell="cell">
<div class="cell__inner country-cell">
<img [src]="cell.row.data.CountryFlag" class="country-flag" #target="tooltipTarget" [igxTooltipTarget]="tooltipRef">
<div #tooltipRef="tooltip" igxTooltip>
{{ cell.row.data.CountryName }}
</div>
</div>
</ng-template>
</igx-column>
<igx-column field="Avatar" header="Photo" dataType="string" width="80" [disablePinning]="true">
<ng-template igxCell let-cell="cell">
<div class="cell__inner avatar-cell">
<igx-avatar [src]="cell.row.data.Avatar" [roundShape]="true" size="small"></igx-avatar>
</div>
</ng-template>
</igx-column>
<igx-column field="Name" header="Name" [disablePinning]="true"></igx-column>
<igx-column field="AthleteNumber" header="Number"></igx-column>
<igx-column field="BeatsPerMinute" header="BPM"></igx-column>
<igx-column field="TopSpeed" header="Top Speed"></igx-column>
<igx-column field="TrackProgress" header="Track Progress" [disablePinning]="true"></igx-column>
<igx-column field="RegistrationDate" header="Date of Registration" width="170" [disablePinning]="true">
<ng-template igxCell let-cell>
{{ cell | date:'longDate' }}
</ng-template>
</igx-column>
<igx-column field="Birthday" header="Birthday" width="170" [disablePinning]="true">
<ng-template igxCell let-cell>
{{ cell | date:'longDate' }}
</ng-template>
</igx-column>
<igx-column field="Sponsor" header="Sponsor Company" width="160"></igx-column>
<igx-column field="Agent" header="Athlete Agent" width="140" [disablePinning]="true"></igx-column>
<igx-column field="AgentContact" header="Agent's Email" width="200" [disablePinning]="true"></igx-column>
<igx-column field="AgentPhone" header="Agent's Phone" width="200" [disablePinning]="true"></igx-column>
<igx-column #goldColumn field="FirstPlaces" header="Gold" width="110" [pinned]="true">
<ng-template igxHeader>
<div class="title-inner">
<span style="float:left">{{ goldColumn.header }}</span>
<igx-icon [style.color]="'#d2c206'">emoji_events</igx-icon>
</div>
</ng-template>
</igx-column>
<igx-column #silverColumn field="SecondPlaces" header="Silver" width="110" [pinned]="true">
<ng-template igxHeader>
<div class="title-inner">
<span style="float:left">{{ silverColumn.header }}</span>
<igx-icon [style.color]="'#c5c5c5'">emoji_events</igx-icon>
</div>
</ng-template>
</igx-column>
<igx-column #bronzeColumn field="ThirdPlaces" header="Bronze" width="110" [pinned]="true">
<ng-template igxHeader>
<div class="title-inner">
<span style="float:left">{{ bronzeColumn.header }}</span>
<igx-icon [style.color]="'#bb8b1d'">emoji_events</igx-icon>
</div>
</ng-template>
</igx-column>
</igx-grid>
</div>
html
.title-inner {
display: flex;
justify-content: space-between;
align-items: center;
}
.grid__wrapper {
margin: 0 auto;
padding: 16px;
}
img.country-flag {
width: 35px;
height: 20px;
}
scss
カスタム列ピン固定 UI
カスタム UI を定義し、関連する API を介して列のピン状態を変更できます。
ツールバーの代わりに、エンドユーザーが特定の列のピンの状態を変更するためにクリックできる列ヘッダーにピンアイコンを定義するとします。
これは、カスタムアイコンを使用して列のヘッダーテンプレートを作成することで実行できます。
<igx-grid #grid1 [data]="data" [width]="'100%'" [height]="'500px'">
<igx-column #col *ngFor="let c of columns" [field]="c.field" [header]="c.header" [width]="c.width" [pinned]='c.pinned'
[hidden]='c.hidden' [headerClasses]="'customHeaderSyle'">
<ng-template igxHeader>
<div class="title-inner">
<span style="float:left">{{col.header}}</span>
<igx-icon class="pin-icon" fontSet="fas" name="fa-thumbtack" (click)="toggleColumn(col)"></igx-icon>
</div>
</ng-template>
</igx-column>
</igx-grid>
html
カスタムアイコンをクリックすると、関連する列のピン状態は、列の API メソッドを使用して変更できます。
public toggleColumn(col: ColumnType) {
col.pinned ? col.unpin() : col.pin();
}
typescript
デモ
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 { PinningSampleComponent } from "./grid/grid-sample-pinning/grid-pinning.component";
import {
IgxGridModule,
IgxIconModule
} from "igniteui-angular";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
PinningSampleComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxGridModule,
IgxIconModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, ViewChild, ViewEncapsulation, OnInit , AfterViewInit} from '@angular/core';
import { IgxColumnComponent, IgxGridComponent, IgxIconService } from 'igniteui-angular';
import { icons } from '../../services/svgIcons';
import { DATA } from '../../data/customers';
const FILTERING_ICONS_FONT_SET = 'filtering-icons';
@Component({
encapsulation: ViewEncapsulation.None,
providers: [],
selector: 'app-grid-sample',
styleUrls: ['grid-pinning.component.scss'],
templateUrl: 'grid-pinning.component.html'
})
export class PinningSampleComponent implements OnInit, AfterViewInit {
@ViewChild('grid1', { static: true }) public grid1: IgxGridComponent;
public data: any[];
public columns: any[];
constructor(private iconService: IgxIconService) {
}
public ngOnInit(): void {
this.columns = [
{ field: 'ID', header: 'ID', width: 100, hidden: true },
{ field: 'CompanyName', header: 'Company Name', width: 300 },
{ field: 'ContactName', header: 'Contact Name', width: 200, pinned: true },
{ field: 'ContactTitle', header: 'Contact Title', width: 200, pinned: true },
{ field: 'Address', header: 'Address', width: 300 },
{ field: 'City', header: 'City', width: 120 },
{ field: 'Region', header: 'Region', width: 120 },
{ field: 'PostalCode', header: 'Postal Code', width: 150 },
{ field: 'Phone', header: 'Phone', width: 150 },
{ field: 'Fax', header: 'Fax', width: 150 }
];
this.data = DATA;
}
public ngAfterViewInit() {
const pinnedIcons = icons.filter(icon => icon.name === 'pin' || icon.name === 'unpin');
pinnedIcons.forEach(icon => {
if (!this.iconService.isSvgIconCached(icon.name, FILTERING_ICONS_FONT_SET)) {
this.iconService.addSvgIconFromText(icon.name, icon.value, FILTERING_ICONS_FONT_SET);
}
});
}
public toggleColumn(col: IgxColumnComponent) {
col.pinned ? col.unpin() : col.pin();
}
}
ts
<div class="grid__wrapper" style='width: 100%;'>
<igx-grid [igxPreventDocumentScroll]="true" #grid1 [data]="data" [width]="'100%'" [height]="'480px'">
<igx-column #col *ngFor="let c of columns" [field]="c.field" [header]="c.header" [width]="c.width"
[pinned]='c.pinned' [hidden]='c.hidden' [headerClasses]="'customHeaderSyle'">
<ng-template igxHeader>
<div class="title-inner">
<span class="header-text">{{col.header}}</span>
<igx-icon class="pin-icon" [class.pinned]="col.pinned" [class.unpinned]="!col.pinned"
family="filtering-icons" name="{{col.pinned ? 'unpin' : 'pin'}}" (click)="toggleColumn(col)">
</igx-icon>
</div>
</ng-template>
</igx-column>
</igx-grid>
</div>
html
.grid__wrapper {
margin: 0 auto;
padding: 16px;
}
.title-inner {
display: flex;
justify-content: space-between;
align-items: center;
}
.header-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pin-icon {
margin-left: 8px;
cursor: pointer;
display: flex;
align-items: center;
}
.pinned {
color: #444;
&:hover {
color: #999;
}
}
.unpinned {
color: #999;
&:hover {
color: #444;
}
}
scss

ピン固定の制限
- 列幅をパーセンテージ (%) で設定した場合にピン固定列があると Grid 本体およびヘッダー コンテンツが正しく配置されません。列のピン固定を正しく設定するには、列幅をピクセル (px) に設定するか、Grid によって自動的に割り当てる必要があります。
スタイル設定
igxGridを使用すると、Ignite UI for Angular テーマ ライブラリ でスタイルを設定できます。grid-theme
は、グリッドのすべての機能をカスタマイズできるさまざまなプロパティを公開します。
以下の手順では、グリッドのピン固定スタイルをカスタマイズする手順を実行しています。
グローバル テーマのインポート
グループ化機能のカスタマイズは、すべてのスタイリング機能とミックスインが配置されている index
ファイルをインポートする必要があります。
@use "igniteui-angular/theming" as *;
scss
カスタム テーマの定義
次に、grid-theme
を拡張し、必要に応じて Group By をカスタマイズするために必要なパラメーターを受け入れる新しいテーマを作成します。
$custom-theme: grid-theme(
$pinned-border-width: 5px,
$pinned-border-style: double,
$pinned-border-color: #ffcd0f,
$cell-active-border-color: #ffcd0f
);
scss
上記のようにカラーの値をハードコーディングする代わりに、palette
および color
関数を使用してカラーに関してより高い柔軟性を実現することができます。使い方の詳細についてはパレット
のトピックをご覧ください。
カスタム テーマの適用
テーマを適用する最も簡単な方法は、グローバル スタイル ファイルに sass
@include
ステートメントを使用することです。
@include css-vars($custom-theme);
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 { PinningStylingComponent } from "./grid/grid-sample-pinning-styling/grid-pinning-styling.component";
import {
IgxGridModule,
IgxIconModule
} from "igniteui-angular";
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive";
@NgModule({
bootstrap: [AppComponent],
declarations: [
AppComponent,
PinningStylingComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxGridModule,
IgxIconModule
],
providers: [],
entryComponents: [],
schemas: []
})
export class AppModule {}
ts
import { Component, ViewChild, ViewEncapsulation, OnInit } from '@angular/core';
import { IgxColumnComponent, IgxGridComponent } from 'igniteui-angular';
import { DATA } from '../../data/customers';
@Component({
encapsulation: ViewEncapsulation.None,
providers: [],
selector: 'app-grid-sample',
styleUrls: ['grid-pinning-styling.component.scss'],
templateUrl: 'grid-pinning-styling.component.html'
})
export class PinningStylingComponent implements OnInit{
@ViewChild('grid1', { static: true }) public grid1: IgxGridComponent;
public data: any[];
public columns: any[];
public ngOnInit(): void {
this.columns = [
{ field: 'ID', header: 'ID', width: 100, hidden: true },
{ field: 'CompanyName', header: 'Company Name', width: 300 },
{ field: 'ContactName', header: 'Contact Name', width: 200, pinned: true },
{ field: 'ContactTitle', header: 'Contact Title', width: 200, pinned: true },
{ field: 'Address', header: 'Address', width: 300 },
{ field: 'City', header: 'City', width: 120 },
{ field: 'Region', header: 'Region', width: 120 },
{ field: 'PostalCode', header: 'Postal Code', width: 150 },
{ field: 'Phone', header: 'Phone', width: 150 },
{ field: 'Fax', header: 'Fax', width: 150 }
];
this.data = DATA;
}
public toggleColumn(col: IgxColumnComponent) {
col.pinned ? col.unpin() : col.pin();
}
}
ts
<div class="grid__wrapper" style='width: 100%;'>
<igx-grid [igxPreventDocumentScroll]="true" #grid1 [data]="data" [width]="'100%'" [height]="'480px'">
<igx-column #col *ngFor="let c of columns" [field]="c.field" [header]="c.header" [width]="c.width" [pinned]='c.pinned'
[hidden]='c.hidden' [headerClasses]="'customHeaderSyle'">
<ng-template igxHeader>
<div class="title-inner">
<span style="float:left">{{col.header}}</span>
<igx-icon class="pin-icon" family="fas" name="fa-thumbtack" (click)="toggleColumn(col)"></igx-icon>
</div>
</ng-template>
</igx-column>
</igx-grid>
</div>
html
@use '../../../variables' as *;
@import url("https://unpkg.com/@fortawesome/fontawesome-free-webfonts@^1.0.9/css/fontawesome.css");
@import url("https://unpkg.com/@fortawesome/fontawesome-free-webfonts@^1.0.9/css/fa-regular.css");
@import url("https://unpkg.com/@fortawesome/fontawesome-free-webfonts@^1.0.9/css/fa-solid.css");
$custom-theme: grid-theme(
$pinned-border-width: 5px,
$pinned-border-style: double,
$pinned-border-color: #FFCD0F,
$cell-active-border-color: #FFCD0F
);
:host {
@include css-vars($custom-theme);
}
.header-icon {
font-size: 1.1em;
width: 1.1em;
height: 1.1em;
float: right;
cursor: pointer;
}
.header {
height: 100%;
}
:host ::ng-deep .title {
width: 100%;
}
.pin-icon {
margin-left: 8px;
font-size: 14px;
cursor: pointer;
display: flex;
align-items: center;
color: #999;
&:hover {
color: #444
}
}
.igx-grid__th--pinned {
.pin-icon {
color: #444;
&:hover {
color: #999
}
}
}
.title-inner {
display: flex;
justify-content: space-between;
align-items: center;
}
.grid__wrapper {
margin: 0 auto;
padding: 16px;
}
scss
このサンプルは、Change Theme
(テーマの変更) から選択したグローバル テーマに影響を受けません。
API リファレンス
その他のリソース
コミュニティに参加して新しいアイデアをご提案ください。