Arrastre de filas en cuadrícula de árbol Angular
En Ignite UI for Angular cuadrícula de árbol, RowDrag se inicializa en el componente raíz igx-tree-grid
y se puede configurar a través de la rowDraggable
entrada. Al habilitar el arrastre de filas, los usuarios disponen de un controlador de arrastre de filas con el que pueden iniciar el arrastre de una fila.
Angular Tree Grid Row Drag Example
Configuración
Para habilitar el arrastre de filas para su igx-tree-grid
, todo lo que necesita hacer es configurar el rowDraggable
de la cuadrícula en true
. Una vez que esto esté habilitado, se mostrará un controlador de arrastre de fila en cada fila. Este controlador se puede utilizar para iniciar el arrastre de filas.
<igx-tree-grid [rowDraggable]="true">
...
</igx-tree-grid>
Al hacer clic en el controlador de arrastre y mover el cursor mientras se mantiene presionado el botón, se activará el evento rowDragStart
de la cuadrícula. Si suelta el clic en cualquier momento, se activará el evento rowDragEnd
.
A continuación, puede encontrar un tutorial sobre cómo configurar un igx-tree-grid
para admitir el arrastre de filas y cómo manejar adecuadamente el evento de colocación.
En este ejemplo, nos encargaremos de arrastrar una fila desde una cuadrícula a un área designada y, al soltarla, la eliminaremos de la cuadrícula.
Drop Areas
Habilitar el arrastre de filas fue bastante fácil, pero ahora tenemos que configurar cómo manejaremos el descenso de filas. Podemos definir dónde queremos que se eliminen nuestras filas usando la igxDrop
directiva .
Primero necesitamos importar IgxDragDropModule
en nuestro módulo de aplicación:
import { ..., IgxDragDropModule } from 'igniteui-angular';
// import { ..., IgxDragDropModule } from '@infragistics/igniteui-angular'; for licensed package
...
@NgModule({
imports: [..., IgxDragDropModule]
})
Luego, en nuestra plantilla, definimos un área de colocación usando el selector de directivas:
<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>
Puede habilitar la animación cuando una fila se coloca en un área no desplegable utilizando el parámetro animation
del evento rowDragEnd
. Si se establece en verdadero, la fila arrastrada volverá a su posición original cuando se suelte sobre un área que no se puede soltar.
Puede habilitar animaciones como esta:
export class IgxTreeGridRowDragComponent {
public onRowDragEnd(args) {
args.animation = true;
}
}
Drop Area Event Handlers
Una vez que hemos definido nuestra área de colocación en la plantilla, tenemos que declarar nuestros controladores para el igxDrop
's enter
, leave
y dropped
eventos en nuestro componente.ts
archivo.
Primero, echemos un vistazo a nuestros controladores enter
y leave
. En esos métodos, solo queremos cambiar el ícono del fantasma del arrastre para poder indicarle al usuario que está encima de un área que le permite soltar la fila:
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;
}
}
}
}
El changeGhostIcon
privado El método simplemente cambia el ícono dentro del fantasma de arrastre. La lógica del método encuentra el elemento que contiene el icono (usando el igx-grid__drag-indicator
clase que se aplica al contenedor del indicador de arrastre), cambiando el texto interno del elemento al pasado. Los iconos en sí son del material
conjunto de fuentes y se definen en un separado enum
:
enum DragIcon {
DEFAULT = 'drag_indicator',
ALLOW = 'remove'
}
A continuación, tenemos que definir qué debería suceder cuando el usuario realmente coloca la fila dentro del área de colocación.
export class IgxTreeGridRowDragComponent {
public onDropAllowed(args: IDropDroppedEventArgs) {
const draggedRow: RowType = args.dragData;
draggedRow.delete();
}
}
Una vez que se elimina la fila, simplemente llamamos al método delete()
de la fila.
Note
Cuando utilice datos de fila de los argumentos del evento (args.dragData.data
) o cualquier otra propiedad de fila, tenga en cuenta que la fila completa se pasa en los argumentos como referencia, lo que significa que debe clonar los datos que necesita, si desea distinguirlo del de la cuadrícula de origen.
Templating the drag ghost
Se puede crear una plantilla para el fantasma de arrastre usando la directiva IgxRowDragGhost
, aplicada a un <ng-template>
dentro del cuerpo de igx-tree-grid
:
<igx-tree-grid>
...
<ng-template igxRowDragGhost>
<div>
<igx-icon fontSet="material">arrow_right_alt</igx-icon>
</div>
</ng-template>
...
</igx-tree-grid>
El resultado de la configuración se puede ver a continuación en una igx-tree-grid
con el arrastre de filas y la selección múltiple habilitada. La demostración muestra el recuento de las filas arrastradas actualmente:
Demostración de ejemplo
Templating the drag icon
El icono del controlador de arrastre se puede crear como plantilla usando dragIndicatorIconTemplate
de la cuadrícula. En el ejemplo que estamos creando, cambiemos el ícono predeterminado (drag_indicator
) a drag_handle
. Para hacerlo, podemos usar igxDragIndicatorIcon
para pasar una plantilla dentro del cuerpo de igx-tree-grid
:
<igx-tree-grid>
...
<ng-template igxDragIndicatorIcon>
<igx-icon>drag_handle</igx-icon>
</ng-template>
...
</igx-tree-grid>
Una vez que hayamos configurado la nueva plantilla de ícono, también necesitamos ajustar el ícono DEFAULT
en nuestra DragIcon enum
, para que se cambie correctamente mediante el método changeIcon
:
enum DragIcon {
DEFAULT = "drag_handle",
...
}
Styling the drop area
Una vez que nuestros controladores de entrega estén configurados correctamente, todo lo que queda es darle un poco de estilo a nuestra área de entrega:
.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%;
}
El resultado se puede ver en la demostración a continuación:
Demostración de ejemplo
Application Demo
Row Reordering Demo
Con la ayuda de los eventos de arrastre de filas de la cuadrícula y la directiva igxDrop
, puede crear una cuadrícula que le permita reordenar las filas arrastrándolas.
Dado que todas las acciones sucederán dentro del cuerpo del grid, ahí es donde debes adjuntar la directiva 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
¡Asegúrese de que haya una primaryKey
especificada para la cuadrícula! La lógica necesita un identificador único para las filas para que puedan reordenarse correctamente.
Una vez que rowDraggable
esté habilitado y se haya definido una zona de colocación, debe implementar un controlador simple para el evento de colocación. Cuando se arrastra una fila, verifique lo siguiente:
- ¿Se amplía la fila? Si es así, colapsarlo.
- ¿Se dejó caer la fila dentro de la cuadrícula?
- Si es así, ¿en qué otra fila se soltó la fila arrastrada?
- Una vez que haya encontrado la fila de destino, intercambie las ubicaciones de los registros en la matriz
data
. - ¿Se seleccionó inicialmente la fila? Si es así, márquelo como seleccionado.
A continuación, puede ver esto implementado en el archivo.ts
del componente:
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;
}
}
¡Con estos sencillos pasos, ha configurado una cuadrícula que permite reordenar filas mediante arrastrar y soltar! Puede ver el código anterior en acción en la siguiente demostración.
Observe que también tenemos habilitada la selección de filas y conservamos la selección al soltar la fila arrastrada.
Limitations
Actualmente, no existen limitaciones conocidas para la directiva rowDraggable
.