Dev & EngARTIGO

Listas interativas com Angular – Drag and Drop

No seguinte artigo, Kheronn Machado apresenta um passo a passo ensinando a implementar o recurso drap and drop aplicado à uma lista com personagens do game Mortal Kombat.

Listas interativas com Angular – Drag and Drop
Imagem: Kheronn Machado

Na versão 7 do AngularAngular30 conteúdosCriando Micro Frontends Angular com Native FederationDev (Back & Front) · mar 2026Angular v21 e o Fim da Cobertura de Testes Exclusivamente em TypeScript: Por Que Precisamos Repensar os Testes de ComponentesDev (Back & Front) · jan 2026Angular 8 é lançado com builder APIs e suporte web workerDev (Back & Front) · mai 2019Ver tudo em Dev (Back & Front) é possível utilizar um aspecto muito interessante para efeitos de interação: o drag and drop, famoso arrasta e solta.

Neste artigo eu mostro como utilizar esse recurso aplicado à uma lista com personagens de um jogo.

Requisitos

Criado o projeto, é necessário incluir as seguintes dependências. No terminal, informe:

bash
$ ng add @angular/material

Aceite a instalação da biblioteca hammerjs e escolha um tema de sua preferência.

Com isso já podemos abrir o módulo principal e definir no array de import o módulo DragDropModule.

Para esse exemplo eu vou utilizar o HttpClientModule para carregar os dados de um arquivo local.

// Outros imports omitidos
'@angular/platform-browser/animations';
import { HttpClientModule } from '@angular/common/http';
import { DragDropModule } from '@angular/cdk/drag-drop';

@NgModule({
 declarations: [
   AppComponent
 ],
 imports: [
   BrowserModule,
   AppRoutingModule,
   BrowserAnimationsModule,
   HttpClientModule,
   DragDropModule

 ],
 providers: [],
 bootstrap: [AppComponent]
})
export class AppModule { }

Na pasta assets vamos criar um arquivo data.json com o seguinte conteúdo:

[
 {
 “name”: “Scorpion”,
 “image”: “https://i.pinimg.com/564x/c4/b2/65/c4b2659a04c7cb1f99c1b2ed738f73d2.jpg",
 “fatality”: “X + L2 + UP”
 },
 {
 “name”: “Subzero”,
 “image”: “https://i.pinimg.com/564x/80/b5/45/80b5458dd048c3457ca54a903de3f7ba.jpg",
 “fatality”: “Up + Down + Up + Kick medium”
 },
 {
 “name”: “Kitana”,
 “image”: “https://i.pinimg.com/originals/4f/cc/cd/4fcccdf78814311d77be47d233db1699.png",
 “fatality”: “X + L2 + UP”
 },
 {
 “name”: “Aang”,
 “image”: “http://rehatron-alpha.eu/images/6321365424_essay-help-forum.png",
 “fatality”: “ L2 + UP”
 }
]

Dessa forma, temos um array de objetos com as propriedades que representam nossos personagens.

Lógica do componente

Abrindo a classe app.component.ts vamos definir uma interface para mapear o personagem com os campos name, image e fatality.

export interface Character {
 name: string;
 image: string;
 fatality: string;
}

Após a assinatura da classe vamos definir dois arrays que representarão nossas listas.

No método construtor fazemos a injeção do HttpClient e chamamos o método getMyList().

A implementação é basicamente um get tipando o resultado para nossa interface <Character[ ]>, informando o caminho da fonte de dados “assets/data.json”.

Ficamos ouvindo a emissão de eventos no subscribe, passando a lista para o mylist.

A próxima função, drop é responsável por duas ações.

Alterar a ordem dos elementos, utilizando a função movieItemInArray e/ou, mudar o item (no caso, os personagens) para outra lista. Para isso utilizamos a função transferArrayItem.

A implementação deve verificar antes, qual a origem (container) do item, através do comando:

javascript
if (event.previousContainer === event.container) {

Segue o código completo da classe.

import { Component } from '@angular/core';
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { HttpClient } from '@angular/common/http';

export interface Character {
  name: string;
  image: string;
  fatality: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  myList: Character[]
  confirmList: Character[] = [];

  constructor(private httpClient: HttpClient) {
    this.getMyList()
  }

  getMyList() {
     this.httpClient.get<Character[]>("assets/data.json")
     .subscribe(list =>{
      this.myList = list;
     })
  }

  drop(event: CdkDragDrop<Character[]>) {
    if (event.previousContainer === event.container) {
      moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
    } else {

      transferArrayItem(event.previousContainer.data,
        event.container.data,
        event.previousIndex,
        event.currentIndex);
    }
  }

}

Template do componente

Vamos codifcar o template. Edite o app.component.html e deixe assim:

<div class="container mx-auto p-2">
  <div class="row p-2">
    <div class="col-lg-12">
      <h1>Mortal Kombat 11</h1>
    </div>
  </div>
  <div class="row">
    <div cdkDropList #minha="cdkDropList" [cdkDropListConnectedTo]="[confirmados]" [cdkDropListData]="myList"
      class="col-lg-6" (cdkDropListDropped)="drop($event)">
      <ul class="list-group">
        <li class="list-group-item list-group-item-danger">
          <h3>Minha Lista</h3>
        </li>
        <li class="list-group-item" *ngFor="let p of myList " cdkDrag>{{p.name}}</li>
      </ul>
    </div>
    <div cdkDropList #confirmados="cdkDropList" [cdkDropListData]="confirmList" [cdkDropListConnectedTo]="[minha]"
      (cdkDropListDropped)="drop($event)" class="col-lg-6">
      <ul class="list-group">
        <li class="list-group-item active">
          <h3>Confirmados</h3>
        </li>
        <li class="list-group-item" *ngFor="let p of confirmList" cdkDrag>
          <img [src]="p.image" class="img-person">
          {{p.name}}</li>
      </ul>
    </div>
  </div>
</div>

As linhas 8 e 17 são os locais onde definimos o container, utilizando a diretiva cdkDropList. Ainda na linha 8 criamos um atributo #minha e atribuímos a diretiva.

Com isso, podemos apontar para qual lista podemos arrastar os personagens, utilizando o atributo [cdkDropListConnectedTo].

Definimos a fonte de dados com [cdkDropListData] e finalmente a função (cdkDropListDropped)=”drop($event)”, responsável pelas ações definidas anteriormente.

Na linha 14 realizamos a iteração da lista com o *ngFor. Importante: aqui também declaramos a diretiva cdkDrag, indicando o elemento que pode ser arrastado.

Note que, a partir da linha 17, codificamos a outra lista, alterando o nome e a fonte.

No arquivo de estilos, codificamos duas animações para alterar a ordem e para soltar o personagem.

javascript
.cdk-drop-list-dragging .cdk-drag {

transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);

}

.cdk-drag-animating {

transition: transform 300ms cubic-bezier(0, 0, 0.2, 1);

}

.img-person {

border-radius: 35%;

width: 80px;

}

Fácil, né?

Até mais!

Mestre em Informática pela Universidade Federal do Paraná. Atuo como professor e assessor pedagógico em Tecnologias Educacionais na rede Estadual de Educação do Paraná, NRE de Wenceslau Braz. Interesse em tecnologias que contribuam para aprendizagem significativa.

Mais de Kheronn Machado
Ver perfil
Leia também