프로젝트 목록을 드래그 앤 드롭을 적용해보자.
먼저 HTML에 원하는 태그에 draggable="true"
속성을 추가하자.
<template id="single-project">
<li draggable="true">
<h2></h2>
<h3></h3>
<p></p>
</li>
</template>
interface Draggable {
dragStartHandler(event: DragEvent): void;
dragEndHandler(event: DragEvent): void;
}
interface DragTarget {
dragOverHandler(event: DragEvent): void;
dragHandler(event: DragEvent): void;
dragLeaveHandler(event: DragEvent): void;
}
위 인터페이스를 사용할 것이다.
이것을 implements 해보자.
class ProjectItem extends Component<HTMLUListElement, HTMLLIElement>
implements Draggable {
// ...
@autobind
dragStartHandler(event: DragEvent) {
event.dataTransfer!.setData('text/plain', this.project.id);
event.dataTransfer!.effectAllowed = 'move';
}
dragEndHandler(_: DragEvent) {
console.log('DragEnd');
}
configure() {
this.element.addEventListener('dragstart', this.dragStartHandler);
this.element.addEventListener('dragend', this.dragEndHandler);
};
}
아이템에 dragstart, dragend를 적용했다.
class ProjectList extends Component<HTMLDivElement, HTMLElement> implements DragTarget {
// ...
@autobind
dragOverHandler(event: DragEvent) {
if (event.dataTransfer?.types[0] === 'text/plain') {
event.preventDefault();
const listEl = this.element.querySelector('ul')!;
listEl.classList.add('droppable');
}
}
@autobind
dragHandler(event: DragEvent) {
const prjId = event.dataTransfer!.getData('text/plain');
projectState.moveProject(
prjId,
this.type === 'active' ? ProjectStatus.Active : ProjectStatus.Finished
);
}
@autobind
dragLeaveHandler(_: DragEvent) {
const listEl = this.element.querySelector('ul')!;
listEl.classList.remove('droppable');
}
configure() {
// ...
this.element.addEventListener('dragover', this.dragOverHandler);
this.element.addEventListener('dragleave', this.dragLeaveHandler);
this.element.addEventListener('drop', this.dragHandler);
}
}
드롭될 목록에 dragover, dragleave, drop 이벤트를 달았다.
드롭될 때 프로젝트 status를 바꾸고 리스너를 업데이트하자.
class ProjectState extends State<Project> {
// ...
moveProject(projectId: string, newStatus: ProjectStatus) {
const project = this.projects.find((prj) => prj.id === projectId);
if (project && project.status !== newStatus) {
project.status = newStatus;
this.updateListeners();
}
}
private updateListeners() {...}
}
완성