Angular Tree Grid の行ドラッグ
Ignite UI for Angular Tree Grid では、RowDrag がルート igx-tree-grid
コンポーネントで初期化されて、rowDraggable
入力で設定できます。行ドラッグを有効にすると、ユーザーは行ドラッグ ハンドルを使用して行のドラッグを開始できます。
Angular Tree 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 { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
import {
IgxTreeGridModule,
IgxButtonModule,
IgxInputGroupModule,
IgxDragDropModule
} from "igniteui-angular" ;
import { TreeGridRowDragBaseComponent } from "./tree-grid-row-drag-base/tree-grid-row-drag-base.component" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
TreeGridRowDragBaseComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule,
IgxButtonModule,
IgxInputGroupModule,
IgxDragDropModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー
import { Component, ViewChild } from '@angular/core' ;
import { IDropDroppedEventArgs, IgxTreeGridComponent, RowType } from 'igniteui-angular' ;
import { FULL_EMPLOYEE_DATA } from '../data/employees' ;
enum DragIcon {
DEFAULT = 'drag_indicator' ,
ALLOW = 'remove'
}
@Component ({
selector : 'app-tree-grid-row-drag-base' ,
styleUrls : ['tree-grid-row-drag-base.component.scss' ],
templateUrl : 'tree-grid-row-drag-base.component.html'
})
export class TreeGridRowDragBaseComponent {
@ViewChild (IgxTreeGridComponent, { read : IgxTreeGridComponent, static : true })
public treeGrid: IgxTreeGridComponent;
public localData = [];
constructor ( ) {
this .localData = FULL_EMPLOYEE_DATA();
}
public onRowDragEnd (args ) {
args.animation = true ;
}
public onDropAllowed (args: IDropDroppedEventArgs ) {
const draggedRow: RowType = args.dragData;
draggedRow.delete();
}
public onEnterAllowed (args ) {
this .changeGhostIcon(args.drag.ghostElement, DragIcon.ALLOW);
}
public onLeaveAllowed (args ) {
this .changeGhostIcon(args.drag.ghostElement, DragIcon.DEFAULT);
}
private changeGhostIcon (ghost, icon: string ) {
if (ghost) {
const currentIcon = ghost.querySelector('.igx-grid__drag-indicator > igx-icon' );
if (currentIcon) {
currentIcon.innerText = icon;
}
}
}
}
ts コピー <div class ="drop-area" igxDrop (enter )="onEnterAllowed($event)" (leave )="onLeaveAllowed($event)"
(dropped )="onDropAllowed($event)" >
<igx-icon > delete</igx-icon >
<div > Drag a row here to delete it</div >
</div >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #treeGrid [data ]="localData" [moving ]="true" childDataKey ="Employees" width ="800px" height ="540px" [autoGenerate ]="false"
[rowDraggable ]="true" [allowFiltering ]="true"
(rowDragEnd )="onRowDragEnd($event)" >
<igx-paginator > </igx-paginator >
<igx-column field ="Name" dataType ="string" [sortable ]="true" [editable ]="true" [resizable ]="true" >
</igx-column >
<igx-column field ="Title" dataType ="string" [sortable ]="true" [editable ]="true" [resizable ]="true" >
</igx-column >
<igx-column field ="HireDate" header ="Hire Date" dataType ="date" [sortable ]="true" [editable ]="true"
[resizable ]="true" width ="150px" > </igx-column >
<igx-column field ="Age" dataType ="number" [sortable ]="true" [editable ]="true" [resizable ]="true"
width ="100px" > </igx-column >
</igx-tree-grid >
html コピー .drop-area {
width : 160px ;
height : 160px ;
background-color : #d3d3d3 ;
border : 1px dashed #131313 ;
display : flex;
justify-content : center;
align-items : center;
flex-flow : column;
text-align : center;
margin : 8px ;
}
:host {
display : flex;
justify-content : space-evenly;
align-items : center;
flex-flow : row;
width : 100% ;
padding-top : 10px ;
}
scss コピー
このサンプルが気に入りましたか? 完全な Ignite UI for Angularツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
構成
igx-tree-grid
の行ドラッグを有効にするには、グリッドの rowDraggable
を true
に設定します。これが有効になると、行ドラッグ ハンドルが各行に表示されます。このハンドルは行ドラッグを開始するために使用できます。
<igx-tree-grid [rowDraggable ]="true" >
...
</igx-tree-grid >
html
ドラッグ ハンドルをクリックしてボタンを押しながらカーソルを動かすと、グリッドの rowDragStart
イベントが発生します。クリックをリリースすると、rowDragEnd
イベントが発生します。
以下は、行ドラッグをサポートするための igx-tree-grid
の設定方法と、ドロップイベントの適切な処理方法についてのチュートリアルです。
この例では、グリッドから指定された領域に行をドラッグし、ドロップするとグリッドから削除します。
ドロップ エリア
行ドラッグを簡単に有効にできました。次は行ドロップを処理する方法を設定する必要があります。
igxDrop
ディレクティブ を使用して、行をドロップする場所を定義できます。
はじめに、アプリ モジュールに IgxDragDropModule
をインポートする必要があります。
import { ..., IgxDragDropModule } from 'igniteui-angular' ;
...
@NgModule ({
imports : [..., IgxDragDropModule]
})
typescript
次にテンプレートでディレクティブのセレクターを使ってドロップ エリアを定義します。
<div class ="drop-area" igxDrop (enter )="onEnterAllowed($event)" (leave )="onLeaveAllowed($event)"
(dropped )="onDropAllowed($event)" >
<igx-icon > delete</igx-icon >
<div > Drag a row here to delete it</div >
</div >
html
rowDragEnd
イベントの animation
パラメーターを使用して、ドロップできない領域に行がドロップされたときにアニメーションを有効にできます。true に設定されている場合、ドラッグされた行は、ドロップできない領域の上にドロップされると元の位置に戻ります。
以下はアニメーションを有効にする方法です。
export class IgxTreeGridRowDragComponent {
public onRowDragEnd (args ) {
args.animation = true ;
}
}
typescript
ドロップ エリア イベント ハンドラー
テンプレートでドロップ領域を定義したら、コンポーネントの .ts
ファイルで igxDrop
の enter
、leave
、dropped
イベントを宣言する必要があります。
はじめに、enter
と leave
ハンドラーを見てみましょう。これらのメソッドでは、ドラッグの ghost のアイコンを変更して、行をドロップできる領域の上にあることをユーザーに示すことができます。
export class IgxTreeGridRowDragComponent {
public onEnterAllowed (args ) {
this .changeGhostIcon(args.drag.ghostElement, DragIcon.ALLOW);
}
public onLeaveAllowed (args ) {
this .changeGhostIcon(args.drag.ghostElement, DragIcon.DEFAULT);
}
private changeGhostIcon (ghost, icon: string ) {
if (ghost) {
const currentIcon = ghost.querySelector('.igx-grid__drag-indicator > igx-icon' );
if (currentIcon) {
currentIcon.innerText = icon;
}
}
}
}
typescript
changeGhostIcon
private メソッドは、ドラッグ ゴースト内のアイコンを変更するだけです。メソッドのロジックは、アイコンを含む要素を検索し (ドラッグ インジケーター コンテナーに適用される igx-grid__drag-indicator
クラスを使用)、要素の内部テキストを渡されたものに変更します。
アイコンは material
フォントセット からのもので、別の enum
で定義されています。
enum DragIcon {
DEFAULT = 'drag_indicator' ,
ALLOW = 'remove'
}
typescript
次に、ユーザーが実際にドロップ領域内に行をドロップ したときに何が起こるかを定義する必要があります。
export class IgxTreeGridRowDragComponent {
public onDropAllowed (args: IDropDroppedEventArgs ) {
const draggedRow: RowType = args.dragData;
draggedRow.delete();
}
}
typescript
行が削除されたら、行の delete()
メソッドを呼び出すだけです。
イベント引数 (args.dragData.data
) または他の行プロパティからの行データを使用する場合、行全体が参照として引数に渡されることに注意してください。つまり、ソースグリッドのデータと区別する必要がある場合は、必要なデータを複製する必要があります。
ドラッグ ゴーストのテンプレート化
ドラッグゴーストは、igx-tree-grid
の本文内の <ng-template>
に適用される IgxRowDragGhost
ディレクティブを使用してテンプレート化できます。
<igx-tree-grid >
...
<ng-template igxRowDragGhost >
<div >
<igx-icon fontSet ="material" > arrow_right_alt</igx-icon >
</div >
</ng-template >
...
</igx-tree-grid >
html
以下は、行ドラッグと複数選択を有効にした igx-tree-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 { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
import {
IgxTreeGridModule,
IgxButtonModule,
IgxInputGroupModule,
IgxIconModule,
IgxDragDropModule
} from "igniteui-angular" ;
import { TreeGridMultiRowDragComponent } from "./tree-grid-multi-row-drag/tree-grid-multi-row-drag.component" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
TreeGridMultiRowDragComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule,
IgxButtonModule,
IgxInputGroupModule,
IgxIconModule,
IgxDragDropModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー import { Component, ViewChild } from '@angular/core' ;
import { GridSelectionMode, IDropDroppedEventArgs, IgxTreeGridComponent } from 'igniteui-angular' ;
import { FULL_EMPLOYEE_DATA } from '../data/employees' ;
@Component ({
selector : 'app-tree-grid-multi-row-drag' ,
styleUrls : ['tree-grid-multi-row-drag.component.scss' ],
templateUrl : 'tree-grid-multi-row-drag.component.html'
})
export class TreeGridMultiRowDragComponent {
@ViewChild (IgxTreeGridComponent, { read : IgxTreeGridComponent, static : true })
public treeGrid: IgxTreeGridComponent;
public selectionMode: GridSelectionMode = 'multiple' ;
public selected = false ;
public ids;
public countIcon = 'drag_indicator' ;
public dragIcon = 'keyboard_backspace' ;
public localData = [];
constructor ( ) {
this .localData = FULL_EMPLOYEE_DATA();
}
public onRowDragEnd (args ) {
args.animation = true ;
}
public handleRowSelectionChange (args ) {
this .ids = args.newSelection;
this .selected = this .ids.length !== 0 ;
}
public onDropAllowed (args: IDropDroppedEventArgs ) {
if (this .selected === false ) {
const draggedRow = args.dragData;
draggedRow.delete();
} else {
this .ids.forEach((rowData ) => {
this .treeGrid.deleteRow(rowData);
});
this .selected = false ;
}
}
public onRowDragStart (args ) {
if (this .selected === false ) {
this .countIcon = `filter_1` ;
} else {
const count = this .ids.length;
this .countIcon = `filter_${count > 9 ? '9_plus' : `${count} ` } ` ;
}
}
public onLeaveAllowed (args ) {
this .onRowDragStart(args);
this .dragIcon = 'keyboard_backspace' ;
}
public onEnterAllowed (args ) {
this .dragIcon = 'remove' ;
}
}
ts コピー <div class ="drop-area" igxDrop (enter )="onEnterAllowed($event)" (leave )="onLeaveAllowed($event)"
(dropped )="onDropAllowed($event)" >
<igx-icon > delete</igx-icon >
<div > Drag a row here to delete it</div >
</div >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #treeGrid [data ]="localData" childDataKey ="Employees" [moving ]="true" width ="800px" height ="580px" [autoGenerate ]="false"
[rowDraggable ]="true" [allowFiltering ]="true" [primaryKey ]="'ID'"
(rowDragEnd )="onRowDragEnd($event)" (rowDragStart )="onRowDragStart($event)"
[rowSelection ]="selectionMode" (rowSelectionChanging )="handleRowSelectionChange($event)" >
<igx-paginator > </igx-paginator >
<igx-column field ="Name" dataType ="string" [sortable ]="true" [editable ]="true" [resizable ]="true" >
</igx-column >
<igx-column field ="Title" dataType ="string" [sortable ]="true" [editable ]="true" [resizable ]="true" >
</igx-column >
<igx-column field ="HireDate" header ="Hire Date" dataType ="date" [sortable ]="true" [editable ]="true"
[resizable ]="true" width ="150px" > </igx-column >
<igx-column field ="Age" dataType ="number" [sortable ]="true" [editable ]="true" [resizable ]="true"
width ="100px" > </igx-column >
<ng-template let-data igxRowDragGhost >
<div class ="allow-drop" >
<igx-icon family ="material" > {{dragIcon}}{{countIcon}}</igx-icon >
</div >
</ng-template >
</igx-tree-grid >
html コピー .drop-area {
width : 160px ;
height : 160px ;
background-color : #d3d3d3 ;
border : 1px dashed #131313 ;
display : flex;
justify-content : center;
align-items : center;
flex-flow : column;
text-align : center;
margin : 8px ;
}
:host {
display : flex;
justify-content : space-evenly;
align-items : center;
flex-flow : row;
width : 100% ;
padding-top : 10px ;
}
.allow-drop {
z-index : 1 ;
}
scss コピー
ドラッグ アイコンのテンプレート化
ドラッグ ハンドル アイコンは、グリッドの dragIndicatorIconTemplate
を使用してテンプレート化できます。作成している例で、アイコンをデフォルトのもの (drag_indicator
) から drag_handle
に変更します。
igxDragIndicatorIcon
を使用して igx-tree-grid
の本文内にテンプレートを渡して変更できます。
<igx-tree-grid >
...
<ng-template igxDragIndicatorIcon >
<igx-icon > drag_handle</igx-icon >
</ng-template >
...
</igx-tree-grid >
html
新しいアイコン テンプレートの設定後、DragIcon enum
の DEFAULT
アイコンも調整する必要があるため、changeIcon
メソッドによって適切に変更されます。
enum DragIcon {
DEFAULT = "drag_handle" ,
...
}
typescript
ドロップ エリアのスタイル
ドロップ ハンドラが正しく設定されたら、次にドロップ領域をスタイル設定します。
.drop-area {
width : 160px ;
height : 160px ;
background-color : #d3d3d3 ;
border : 1px dashed #131313 ;
display : flex;
justify-content : center;
align-items : center;
flex-flow : column;
text-align : center;
margin : 8px ;
}
:host {
display : flex;
justify-content : center;
align-items : center;
flex-flow : column;
width : 100% ;
}
css
結果は以下のデモで確認できます。
デモ
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,
IgxButtonModule,
IgxInputGroupModule,
IgxIconModule,
IgxDragDropModule
} from "igniteui-angular" ;
import { TreeGridRowDragComponent } from "./tree-grid-row-drag/tree-grid-row-drag.component" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
TreeGridRowDragComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule,
IgxButtonModule,
IgxInputGroupModule,
IgxIconModule,
IgxDragDropModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー
import { Component, ViewChild } from '@angular/core' ;
import { IDropDroppedEventArgs, IgxTreeGridComponent, RowType } from 'igniteui-angular' ;
import { FULL_EMPLOYEE_DATA } from '../data/employees' ;
enum DragIcon {
DEFAULT = 'drag_handle' ,
ALLOW = 'remove'
}
@Component ({
selector : 'app-tree-grid-row-drag' ,
styleUrls : ['tree-grid-row-drag.component.scss' ],
templateUrl : 'tree-grid-row-drag.component.html'
})
export class TreeGridRowDragComponent {
@ViewChild (IgxTreeGridComponent, { read : IgxTreeGridComponent, static : true })
public treeGrid: IgxTreeGridComponent;
public localData = [];
constructor ( ) {
this .localData = FULL_EMPLOYEE_DATA();
}
public onRowDragEnd (args ) {
args.animation = true ;
}
public onDropAllowed (args: IDropDroppedEventArgs ) {
const draggedRow: RowType = args.dragData;
draggedRow.delete();
}
public onEnterAllowed (args ) {
this .changeGhostIcon(args.drag.ghostElement, DragIcon.ALLOW);
}
public onLeaveAllowed (args ) {
this .changeGhostIcon(args.drag.ghostElement, DragIcon.DEFAULT);
}
private changeGhostIcon (ghost, icon: string ) {
if (ghost) {
const currentIcon = ghost.querySelector('.igx-grid__drag-indicator > igx-icon' );
if (currentIcon) {
currentIcon.innerText = icon;
}
}
}
}
ts コピー <div class ="drop-area" igxDrop (enter )="onEnterAllowed($event)" (leave )="onLeaveAllowed($event)"
(dropped )="onDropAllowed($event)" >
<igx-icon > delete</igx-icon >
<div > Drag a row here to delete it</div >
</div >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #treeGrid [data ]="localData" [moving ]="true" childDataKey ="Employees" width ="800px" height ="540px" [autoGenerate ]="false"
[rowDraggable ]="true" [allowFiltering ]="true" [primaryKey ]="'ID'" (rowDragEnd )="onRowDragEnd($event)" >
<igx-paginator > </igx-paginator >
<igx-column field ="Name" dataType ="string" [sortable ]="true" [editable ]="true" [resizable ]="true" >
</igx-column >
<igx-column field ="Title" dataType ="string" [sortable ]="true" [editable ]="true" [resizable ]="true" >
</igx-column >
<igx-column field ="HireDate" header ="Hire Date" dataType ="date" [sortable ]="true" [editable ]="true"
[resizable ]="true" width ="150px" > </igx-column >
<igx-column field ="Age" dataType ="number" [sortable ]="true" [editable ]="true" [resizable ]="true"
width ="100px" > </igx-column >
<ng-template igxDragIndicatorIcon >
<igx-icon > drag_handle</igx-icon >
</ng-template >
</igx-tree-grid >
html コピー .drop-area {
width : 160px ;
height : 160px ;
background-color : #d3d3d3 ;
border : 1px dashed #131313 ;
display : flex;
justify-content : center;
align-items : center;
flex-flow : column;
text-align : center;
margin : 8px ;
}
:host {
display : flex;
justify-content : space-evenly;
align-items : center;
flex-flow : row;
width : 100% ;
padding-top : 10px ;
}
scss コピー
アプリケーション デモ
行の並べ替えデモ
グリッドの行ドラッグ イベントと igxDrop
ディレクティブを使用して、ドラッグよる行の並べ替えるが可能なグリッドを作成できます。
すべてのアクションはグリッド本体の内側で発生するため、ここで igxDrop
ディレクティブをアタッチする必要があります:
<igx-tree-grid igxPreventDocumentScroll #treeGrid [data ]="localData" [rowDraggable ]="true" foreignKey ="ParentID"
[primaryKey ]="'ID'" (rowDragStart )="rowDragStart($event)" igxDrop (dropped )="dropInGrid($event)" >
...
</igx-tree-grid >
html
グリッドに primaryKey
が指定されていることを確認してください!ロジックが行を適切に並べ替えられるように、行には一意の識別子が必要です。
rowDraggable
が有効になり、ドロップ エリアが定義されたら、ドロップ イベントの単純なハンドラーを実装する必要があります。行をドラッグするときは、以下を確認してください:
行が展開されていますか? そうであれば、行を縮小します。
行はグリッド内にドロップされましたか?
そうであれば、ドラッグされた行が他のどの行にドロップされましたか?
ターゲット行が見つかれば、data
配列内のレコードの位置を入れ替えます。
行は最初に選択されてましたか? そうであれば、選択済みとしてマークします。
以下では、コンポーネントの .ts
ファイルに実装されていることがわかります。
export class TreeGridRowReorderComponent {
public rowDragStart(args: any ): void {
const targetRow = args.dragData;
if (targetRow.expanded) {
this .treeGrid.collapseRow(targetrow.key);
}
}
public dropInGrid(args: IDropDroppedEventArgs): void {
const draggedRow = args.dragData;
const event = args.originalEvent;
const cursorPosition: Point = { x : event.clientX, y : event.clientY };
this .moveRow(draggedRow, cursorPosition);
}
private moveRow(draggedRow: RowType, cursorPosition : Point): void {
const row = this .catchCursorPosOnElem(this .treeGrid.rowList.toArray(), cursorPosition);
if (!row) { return ; }
if (row.data.ParentID === -1 ) {
this .performDrop(draggedRow, row).ParentID = -1 ;
} else {
if (row.data.ParentID === draggedrow.data.ParentID) {
this .performDrop(draggedRow, row);
} else {
const rowIndex = this .getRowIndex(draggedrow.data);
this .localData[rowIndex].ParentID = row.data.ParentID;
}
}
if (draggedRow.selected) {
this .treeGrid.selectRows([this .treeGrid.rowList.toArray()
.find((r ) => r.rowID === draggedrow.key).rowID], false );
}
this .localData = [...this.localData];
}
private performDrop (
draggedRow: IgxTreeGridRowComponent, targetRow: IgxTreeGridRowComponent ) {
const draggedRowIndex = this .getRowIndex(draggedrow.data);
const targetRowIndex: number = this .getRowIndex(targetrow.data);
if (draggedRowIndex === -1 || targetRowIndex === -1 ) { return ; }
this .localData.splice(draggedRowIndex, 1 );
this .localData.splice(targetRowIndex, 0 , draggedrow.data);
return this .localData[targetRowIndex];
}
private getRowIndex(rowData: any ): number {
return this .localData.indexOf(rowData);
}
private catchCursorPosOnElem(rowListArr: IgxTreeGridRowComponent[], cursorPosition : Point)
: IgxTreeGridRowComponent {
for (const row of rowListArr) {
const rowRect = row.nativeElement.getBoundingClientRect();
if (cursorPosition.y > rowRect.top + window .scrollY && cursorPosition.y < rowRect.bottom + window .scrollY &&
cursorPosition.x > rowRect.left + window .scrollX && cursorPosition.x < rowRect.right + window .scrollX) {
return row;
}
}
return null ;
}
}
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 { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
import {
IgxTreeGridModule,
IgxDragDropModule
} from "igniteui-angular" ;
import { TreeGridRowReorderComponent } from "./tree-grid-row-reorder/tree-grid-row-reorder.component" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
TreeGridRowReorderComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxTreeGridModule,
IgxDragDropModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー import { Component, ViewChild } from '@angular/core' ;
import { IDropDroppedEventArgs,
IgxTreeGridComponent, RowType, Point, GridSelectionMode } from 'igniteui-angular' ;
import { generateEmployeeFlatData } from '../data/employees-flat' ;
@Component ({
selector : 'app-tree-grid-row-reorder' ,
styleUrls : ['tree-grid-row-reorder.component.scss' ],
templateUrl : 'tree-grid-row-reorder.component.html'
})
export class TreeGridRowReorderComponent {
@ViewChild (IgxTreeGridComponent, { read : IgxTreeGridComponent, static : true })
public treeGrid: IgxTreeGridComponent;
public selectionMode: GridSelectionMode = 'multiple' ;
public localData = [];
constructor ( ) {
this .localData = generateEmployeeFlatData();
}
public rowDragStart(args: any ): void {
const targetRow: RowType = args.dragData;
if (targetRow.expanded) {
this .treeGrid.collapseRow(targetRow.key);
}
}
public dropInGrid(args: IDropDroppedEventArgs): void {
const draggedRow: RowType = args.dragData;
const event = args.originalEvent;
const cursorPosition: Point = { x : event.clientX, y : event.clientY };
this .moveRow(draggedRow, cursorPosition);
}
private moveRow(draggedRow: RowType, cursorPosition : Point): void {
const row = this .catchCursorPosOnElem(this .treeGrid.rowList.toArray(), cursorPosition);
if (!row) { return ; }
if (row.key === draggedRow.key) {
return ;
}
if (row.data.ParentID === -1 ) {
this .performDrop(draggedRow, row).ParentID = -1 ;
} else {
if (row.data.ParentID === draggedRow.data.ParentID) {
this .performDrop(draggedRow, row);
} else {
const rowIndex = this .getRowIndex(draggedRow.data);
this .localData[rowIndex].ParentID = row.data.ParentID;
}
}
if (draggedRow.selected) {
this .treeGrid.selectRows([this .treeGrid.rowList.toArray()
.find((r ) => r.key === draggedRow.key).key], false );
}
this .localData = [...this.localData];
}
private performDrop (
draggedRow: RowType, targetRow: RowType ) {
const draggedRowIndex = this .getRowIndex(draggedRow.data);
const targetRowIndex: number = this .getRowIndex(targetRow.data);
if (draggedRowIndex === -1 || targetRowIndex === -1 ) { return ; }
this .localData.splice(draggedRowIndex, 1 );
this .localData.splice(targetRowIndex, 0 , draggedRow.data);
return this .localData[targetRowIndex];
}
private getRowIndex(rowData: any ): number {
return this .localData.indexOf(rowData);
}
private catchCursorPosOnElem(rowListArr: any [], cursorPosition : Point): any {
for (const row of rowListArr) {
const rowRect = row.nativeElement.getBoundingClientRect();
if (cursorPosition.y > rowRect.top + window .scrollY && cursorPosition.y < rowRect.bottom + window .scrollY &&
cursorPosition.x > rowRect.left + window .scrollX && cursorPosition.x < rowRect.right + window .scrollX) {
return row;
}
}
return null ;
}
}
ts コピー <div class ="grid_wrapper" >
<igx-tree-grid [igxPreventDocumentScroll ]="true" #treeGrid igxDrop [moving ]="true" [data ]="localData" childDataKey ="Employees" height ="530px"
[autoGenerate ]="false" [rowDraggable ]="true" foreignKey ="ParentID" [rowSelection ]="selectionMode"
[primaryKey ]="'ID'" (rowDragStart )="rowDragStart($event)" (dropped )="dropInGrid($event)" >
<igx-paginator > </igx-paginator >
<igx-column field ="Name" dataType ="string" [sortable ]="true" [editable ]="true"
[resizable ]="true" >
</igx-column >
<igx-column field ="Title" dataType ="string" [sortable ]="true" [editable ]="true"
[resizable ]="true" >
</igx-column >
<igx-column field ="HireDate" header ="Hire Date" dataType ="date" [sortable ]="true" [editable ]="true"
[resizable ]="true" width ="150px" >
</igx-column >
<igx-column field ="Age" dataType ="number" [sortable ]="true" [editable ]="true"
[resizable ]="true" width ="100px" >
</igx-column >
</igx-tree-grid >
</div >
html コピー .grid_wrapper {
max-width : 0 16px ;
padding : 10px ;
}
scss コピー
制限
現在、rowDraggable
ディレクティブに既知の制限はありません。
API リファレンス
その他のリソース
コミュニティに参加して新しいアイデアをご提案ください。