Arrastar linha em Angular grade hierárquica
Em Ignite UI for Angular Grade hierárquica, RowDrag é inicializado no componente raiz igx-hierarchical-grid
e é configurável por meio da rowDraggable
entrada. Habilitar o arrastar de linha fornece aos usuários uma alça de arrastar de linha com a qual eles podem iniciar o arrasto de uma linha.
Angular Hierarchical Grid Row Drag Example
Configuração
Para habilitar o arrasto de linha para você igx-hierarchical-grid
, tudo o que você precisa fazer é definir a grade rowDraggable
para true
. Depois que isso estiver ativado, uma alça de arrastar linha será exibida em cada linha. Essa alça pode ser usada para iniciar o arrasto de linha.
<igx-hierarchical-grid [rowDraggable]="true">
...
</igx-hierarchical-grid>
Clicar na alça de arrastar e mover o cursor enquanto mantém pressionado o botão fará com que o evento da rowDragStart
grade seja acionado. Liberar o clique a qualquer momento fará com que rowDragEnd
o evento seja acionado.
Abaixo, você pode encontrar um passo a passo sobre como configurar um igx-hierarchical-grid
para dar suporte ao arrasto de linha e como lidar corretamente com o evento de soltar.
Neste exemplo, vamos lidar com arrastar uma linha de uma grade para uma área designada e, ao soltá-la, removê-la da grade.
Drop Areas
Habilitar o arrasto de linha foi muito fácil, mas agora temos que configurar como lidaremos com a queda de linha. Podemos definir onde queremos que nossas linhas sejam descartadas usando a igxDrop
diretiva.
Primeiro, precisamos importar o em nosso módulo de IgxDragDropModule
aplicativo:
import { ..., IgxDragDropModule } from 'igniteui-angular';
// import { ..., IgxDragDropModule } from '@infragistics/igniteui-angular'; for licensed package
...
@NgModule({
imports: [..., IgxDragDropModule]
})
Em seguida, em nosso modelo, definimos uma área de soltar usando o seletor da diretiva:
<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>
Você pode ativar a animação quando uma linha é solta em uma área não soltável usando o animation
rowDragEnd
parâmetro do evento. Se definido como true, a linha arrastada será animada de volta à sua posição original quando solta sobre uma área que não pode ser solta.
Você pode habilitar a animação assim:
export class IgxHierarchicalGridRowDragComponent {
public onRowDragEnd(args) {
args.animation = true;
}
}
Drop Area Event Handlers
Depois de definirmos nossa área de soltar no modelo, temos que declarar nossos manipuladores para os igxDrop
enter
eventos leave
dropped
e eventos no arquivo do.ts
nosso componente.
Primeiro, vamos dar uma olhada em nossos enter
manipuladores leave
. Nesses métodos, queremos apenas alterar o ícone do fantasma do drag para que possamos indicar ao usuário que ele está acima de uma área que permite soltar a linha:
export class IgxHierarchicalGridRowDragComponent {
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;
}
}
}
}
O changeGhostIcon
método privado apenas altera o ícone dentro do fantasma de arrastar. A lógica no método localiza o elemento que contém o ícone (usando a igx-grid__drag-indicator
classe aplicada ao contêiner indicador de arrastar), alterando o texto interno do elemento para o passado. Os ícones em si são do material
fontesconjunto de e são definidos em separado enum
:
enum DragIcon {
DEFAULT = 'drag_indicator',
ALLOW = 'remove'
}
Em seguida, temos que definir o que deve acontecer quando o usuário realmente solta a linha dentro da área de soltar.
export class IgxHierarchicalGridRowDragComponent {
public onDropAllowed(args: IDropDroppedEventArgs) {
const draggedRow: RowType = args.dragData;
draggedRow.delete();
}
}
Depois que a linha é descartada, apenas chamamos o método da delete()
linha
Note
Ao usar dados de linha dos argumentos do evento (args.dragData.data
) ou qualquer outra propriedade de linha, observe que a linha inteira é passada nos argumentos como referência, o que significa que você deve clonar os dados necessários, se quiser distingui-los dos da grade de origem.
Templating the drag ghost
O fantasma de arrastar pode ser modelado usando a IgxRowDragGhost
diretiva, aplicada a um <ng-template>
interior do igx-hierarchical-grid
corpo:
<igx-hierarchical-grid>
...
<ng-template igxRowDragGhost>
<div>
<igx-icon fontSet="material">arrow_right_alt</igx-icon>
</div>
</ng-template>
...
</igx-hierarchical-grid>
O resultado da configuração pode ser exibido abaixo em um igx-hierarchical-grid
com arrastar linhas e seleção múltipla habilitada. A demonstração mostra a contagem das linhas arrastadas no momento:
Exemplo de demonstração
O fantasma de arrastar pode ser modelado em todos os níveis de grade, tornando possível ter vários modelos fantasmas ou fornecer apenas um modelo para uma única ilha de linha.
<igx-hierarchical-grid>
...
<ng-template igxRowDragGhost>
<div>
<igx-icon fontSet="material">arrow_right_alt</igx-icon>
</div>
</ng-template>
<igx-row-island>
...
<ng-template IgxRowDragGhost>
<img src="smile.gif" height="42" width="42">
</ng-template>
</igx-row-island>
...
</igx-hierarchical-grid>
Templating the drag icon
O ícone da alça de arrastar pode ser modelado usando o da grade dragIndicatorIconTemplate
. No exemplo que estamos construindo, vamos alterar o ícone do padrão (drag_indicator
) para drag_handle
. Para fazer isso, podemos usar o igxDragIndicatorIcon
para passar um modelo dentro do igx-hierarchical-grid
corpo:
<igx-hierarchical-grid>
...
<ng-template igxDragIndicatorIcon>
<igx-icon>drag_handle</igx-icon>
</ng-template>
...
</igx-hierarchical-grid>
Depois de definir o novo modelo de ícone, também precisamos ajustar o DEFAULT
ícone em nosso DragIcon enum
, para que ele seja alterado corretamente pelo changeIcon
método:
enum DragIcon {
DEFAULT = "drag_handle",
...
}
Styling the drop area
Uma vez que nossos manipuladores de drop estejam configurados corretamente, tudo o que resta é estilizar um pouco nossa área de drop:
.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%;
}
O resultado pode ser visto na demonstração abaixo:
Exemplo de demonstração
Application Demo
Row Reordering Demo
Com a ajuda dos eventos de arrastar linha da grade e da igxDrop
diretiva, você pode criar uma grade que permite reordenar as linhas arrastando-as.
Como todas as ações acontecerão dentro do corpo da grade, é aí que você deve anexar a igxDrop
diretiva:
<igx-hierarchical-grid #grid [data]="localData" [primaryKey]="'id'"
[rowDraggable]="true" (rowDragStart)="rowDragStart($event)" igxDrop (dropped)="rowDrop($event)">
...
</igx-hierarchical-grid>
Note
Certifique-se de que haja um primaryKey
especificado para a grade! A lógica precisa de um identificador exclusivo para as linhas para que possam ser reordenadas corretamente
Uma vez rowDraggable
habilitado e uma zona de queda definida, você precisa implementar um manipulador simples para o evento de queda. Quando uma linha é arrastada, verifique o seguinte:
- A linha é expandida? Em caso afirmativo, recolha-o.
- A linha foi lançada dentro da grade?
- Em caso afirmativo, em qual outra linha a linha arrastada foi solta?
- Depois de encontrar a linha de destino, troque os lugares dos registros na
data
matriz - A linha foi inicialmente selecionada? Em caso afirmativo, marque-o como selecionado.
Abaixo, você pode ver isso implementado no arquivo do.ts
componente:
export class HGridRowReorderComponent {
public rowDragStart(args: any): void {
const targetRow = args.dragData;
if (targetRow.expanded) {
targetRow.expanded = false;
}
}
public rowDrop(args: IDropDroppedEventArgs): void {
const targetRow = args.dragData;
const event = args.originalEvent;
const cursorPosition: Point = { x: event.clientX, y: event.clientY };
this.moveRow(targetRow, cursorPosition);
}
private moveRow(draggedRow: RowType, cursorPosition: Point): void {
// const parent: IgxHierarchicalGridComponent = (draggedRow as any).grid;
// const parent = args.drag.ghostContext.grid;
const parent = this.hGrid;
const rowIndex: number = this.getTargetRowIndex(parent.rowList.toArray(), cursorPosition);
if (rowIndex === -1) { return; }
const wasSelected = draggedRow.selected;
draggedRow.delete();
parent.data.splice(rowIndex, 0, draggedRow.data);
if (wasSelected) {
parent.selectRows([parent.rowList.toArray()
.find((r) => r.rowID === draggedRow.key).rowID], false);
}
}
private getTargetRowIndex(rowListArr: RowType[], cursorPosition: Point): number {
const targetElem: IgxHierarchicalRowComponent = this.catchCursorPosOnElem(rowListArr, cursorPosition);
return rowListArr.indexOf(rowListArr.find((r) => r.rowData.id === targetElem.rowData.id));
}
private catchCursorPosOnElem(rowListArr: any[], cursorPosition: Point)
: IgxHierarchicalRowComponent {
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;
} else if (row === rowListArr[rowListArr.length - 1] && cursorPosition.y > rowRect.bottom) {
return row;
}
}
}
}
Com essas etapas fáceis, você configurou uma grade que permite reordenar linhas por meio de arrastar/soltar! Você pode ver o código acima em ação na demonstração a seguir.
Observe que também temos a seleção de linha habilitada e preservamos a seleção ao soltar a linha arrastada.
Limitations
Atualmente, não há limitações conhecidas para a rowDraggable
diretiva.