Angular 트리 그리드에서 행 끌기
Ignite UI for Angular에서 RowDrag는 루트 igx-tree-grid
구성 요소에서 초기화되고 rowDraggable
입력을 통해 구성 가능합니다. 행 끌기를 활성화하면 사용자에게 행 끌기를 시작할 수 있는 행 끌기 핸들이 제공됩니다.
Angular Tree Grid Row Drag Example
구성
igx-tree-grid
에 대해 행 드래그를 활성화하려면 그리드의 rowDraggable
true
로 설정하기만 하면 됩니다. 이 기능이 활성화되면 행 끌기 핸들이 각 행에 표시됩니다. 이 핸들을 사용하여 행 끌기를 시작할 수 있습니다.
<igx-tree-grid [rowDraggable]="true">
...
</igx-tree-grid>
드래그 핸들을 클릭하고 버튼을 누른 채 커서를 움직이면 그리드의 rowDragStart
이벤트가 시작됩니다. 언제든지 클릭을 놓으면 rowDragEnd
이벤트가 발생합니다.
아래에서는 행 드래그를 지원하도록 igx-tree-grid
구성하는 방법과 드롭 이벤트를 적절하게 처리하는 방법에 대한 연습을 찾을 수 있습니다.
이 예에서는 그리드에서 지정된 영역으로 행을 드래그하는 작업을 처리하고, 이를 놓을 때 그리드에서 제거합니다.
Drop Areas
행 드래그를 활성화하는 것은 매우 쉬웠지만 이제 행 삭제를 처리하는 방법을 구성해야 합니다. igxDrop
지시문을 사용하여 행을 삭제할 위치를 정의할 수 있습니다.
먼저 앱 모듈에서 IgxDragDropModule
을 가져와야 합니다.
import { ..., IgxDragDropModule } from 'igniteui-angular';
// import { ..., IgxDragDropModule } from '@infragistics/igniteui-angular'; for licensed package
...
@NgModule({
imports: [..., IgxDragDropModule]
})
그런 다음 템플릿에서 지시어 선택기를 사용하여 드롭 영역을 정의합니다.
<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>
다음을 사용하여 놓을 수 없는 영역에 행을 놓을 때 애니메이션을 활성화할 수 있습니다. animation
매개변수 rowDragEnd
이벤트. true로 설정하면 드래그된 행을 놓을 수 없는 영역 위에 놓으면 원래 위치로 다시 애니메이션이 적용됩니다.
다음과 같이 애니메이션을 활성화할 수 있습니다:
export class IgxTreeGridRowDragComponent {
public onRowDragEnd(args) {
args.animation = true;
}
}
Drop Area Event Handlers
템플릿에 놓기 영역을 정의한 후에는 해당 항목에 대한 핸들러를 선언해야 합니다. igxDrop
'에스 enter
, leave
그리고 dropped
우리 컴포넌트의 이벤트.ts
파일.
먼저, enter
및 leave
핸들러를 살펴보겠습니다. 이러한 방법에서는 드래그의 고스트 아이콘을 변경하여 사용자에게 행을 드롭할 수 있는 영역 위에 있음을 표시할 수 있습니다.
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;
}
}
}
}
changeGhostIcon
비공개 메소드는 드래그 고스트 내부의 아이콘을 변경합니다. 메서드의 로직은 드래그 표시기 컨테이너에 적용되는 igx-grid__drag-indicator
클래스를 사용하여 아이콘이 포함된 요소를 찾아 요소의 내부 텍스트를 전달된 텍스트로 변경합니다. 아이콘 자체는 material
글꼴 세트에서 가져온 것이며 별도의 enum
에 정의됩니다.
enum DragIcon {
DEFAULT = 'drag_indicator',
ALLOW = 'remove'
}
다음으로 사용자가 실제로 놓기 영역 내부에 행을 놓을 때 어떤 일이 발생해야 하는지 정의해야 합니다.
export class IgxTreeGridRowDragComponent {
public onDropAllowed(args: IDropDroppedEventArgs) {
const draggedRow: RowType = args.dragData;
draggedRow.delete();
}
}
행이 삭제되면 해당 행의 delete()
메서드를 호출하기만 하면 됩니다.
Note
이벤트 인수(args.dragData.data
) 또는 다른 행 속성의 행 데이터를 사용하는 경우 전체 행이 인수에 참조로 전달됩니다. 즉, 원하는 경우 필요한 데이터를 복제해야 합니다. 이를 소스 그리드의 것과 구별합니다.
Templating the drag ghost
드래그 고스트는 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>
구성 결과는 행 드래그 및 다중 선택이 활성화된 igx-tree-grid
에서 아래에 표시될 수 있습니다. 데모에서는 현재 드래그된 행의 개수를 보여줍니다.
예제 데모
Templating the drag icon
드래그 핸들 아이콘은 그리드의 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>
새 아이콘 템플릿을 설정한 후에는 DragIcon enum
의 DEFAULT
아이콘도 조정해야 합니다. 그러면 changeIcon
메서드에 의해 적절하게 변경됩니다.
enum DragIcon {
DEFAULT = "drag_handle",
...
}
Styling the drop area
드롭 핸들러가 올바르게 구성되면 남은 것은 드롭 영역의 스타일을 약간 지정하는 것입니다.
.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%;
}
결과는 아래 데모에서 확인할 수 있습니다.
예제 데모
Application Demo
Row Reordering Demo
그리드의 행 드래그 이벤트와 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>
Note
그리드에 대해 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;
}
}
이러한 몇 가지 간단한 단계를 통해 드래그/드롭을 통해 행을 재정렬할 수 있는 그리드를 구성했습니다! 다음 데모에서 위 코드가 실제로 작동하는 모습을 볼 수 있습니다.
또한 행 선택이 활성화되어 있으며 드래그된 행을 삭제할 때 선택이 유지됩니다.
Limitations
현재 rowDraggable
지시어에 대해 알려진 제한 사항은 없습니다.