드래그 앤 드롭 적용

jeongwon yun·2023년 3월 6일
0

Typescript

목록 보기
21/25

프로젝트 목록을 드래그 앤 드롭을 적용해보자.

먼저 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() {...}
}

완성

0개의 댓글