프로젝트

노션 (자바스크립트) 클론 코딩 (6) 삭제 및 추가 구현하기

알럽유 2024. 11. 19. 00:01
728x90
반응형
import { request } from '../utils/api.js'
import NewBtn from './NewBtn.js'

export default function SidebarPage({ $target, initalState }) {
    this.state = initalState

    this.createTreeView = (data) => {
        let str = ''
        for (const key in data) {
            if (data[key].documents.length > 0) {
                str += `
                    <li class="dataList">
                        📄 ${data[key].title}
                        <button class="addBtn">➕</button>
                        <button class="delBtn" data-id="${
                            data[key].id
                        }">🗑️</button>
                        <ul>${this.createTreeView(data[key].documents)}</ul>
                    </li>`
            } else {
                str += `
                    <li class="dataList">
                        📄 ${data[key].title}
                        <button class="addBtn">➕</button>
                        <button class="delBtn" data-id="${data[key].id}">🗑️</button>
                    </li>`
            }
        }
        return str
    }

    const $page = document.createElement('div')
    $page.classList.add('listContainer')

    // 렌더링 함수
    this.render = () => {
        $page.innerHTML = `
        <ul class="documentList">
            ${this.state
                .map(
                    (document) =>
                        `<li class="dataList">📄 ${document.title}
                        <button class="addBtn">➕</button>
                        <button class="delBtn" data-id="${
                            document.id
                        }">🗑️</button>
                        ${
                            document.documents.length > 0
                                ? `<ul> ${this.createTreeView(
                                      document.documents
                                  )}</ul>`
                                : ''
                        }
                    </li>`
                )
                .join('')}
        </ul>
    `
    }

    this.render()
    $target.appendChild($page)

    new NewBtn({ $target: $page })

    this.setState = async () => {
        const documentList = await request(``)
        this.state = documentList
        this.render()
    }

    $page.addEventListener('click', async (e) => {
        if (e.target.classList.contains('delBtn')) {
            const id = e.target.dataset.id
            if (id) {
                await request(`/${id}`, {
                    method: 'DELETE',
                })
                this.setState()
            }
        }
    })
}

 

 <button class="delBtn" data-id="${document.id}">🗑️</button>

 

 를 통해서 클래스를 부여하고 

$page.addEventListener('click', async (e) => {
        if (e.target.classList.contains('delBtn')) {
            const id = e.target.dataset.id
            if (id) {
                await request(`/${id}`, {
                    method: 'DELETE',
                })
                this.setState()
            }
        }
    })

 

를 통해서 아이디를 받아와서 삭제를 해주면 됩니다.

 

classList.contains('delBtn'): 클릭된 요소에 delBtn 클래스가 포함되어 있는지 확인합니다.

클릭된 요소가 삭제 버튼(.delBtn)인지 확인합니다.

삭제 버튼이 아닌 다른 요소를 클릭했을 경우 아무 작업도 수행하지 않습니다.

 

이제 추가 기능을 구현하기 이전에 파일 구조를 다시 한번 재정비하고 진행하겠습니다.

components폴더안에 sidebar폴더를 만들고 그 안에 SidebarPage.js SidebarList.js 파일과 NewBtn.js파일들을 넣겠습니다. 

 

SidebarPage.js (껍데기 느낌)

import NewBtn from './NewBtn.js'
import SideBarList from './SidebarList.js'
import { request } from '../../utils/api.js'

export default function SidebarPage({ $target, initalState }) {
    const $page = document.createElement('div')
    $target.appendChild($page)

    $page.classList.add('listContainer')
    const $sidebarList = new SideBarList({
        $target: $page,
        initalState,
    })

    this.setState = () => {
        $sidebarList.setState()
    }

    const onCreate = () => {
        request('', {
            method: 'POST',
            body: JSON.stringify({
                title: '문서 제목2',
                // parent가 null이면 루트 Document가 됩니다.
                // 특정 Document에 속하게 하려면 parent에
                // 해당 Document id를 넣으세요.
                parent: null,
            }),
        })
        $sidebarList.setState()
    }

    const $newBtn = new NewBtn({ $target: $page, onCreate })
}

 

const onCreate = () => {
        request('', {
            method: 'POST',
            body: JSON.stringify({
                title: '문서 제목2',
                // parent가 null이면 루트 Document가 됩니다.
                // 특정 Document에 속하게 하려면 parent에
                // 해당 Document id를 넣으세요.
                parent: null,
            }),
        })
        $sidebarList.setState()
    }

create함수를 작성하고 NewBtn에 넘겨줍니다. 이함수는 게시글을 생성하는 함수입니다.

 

SidebarList.js

import { request } from '../../utils/api.js'
function SideBarList({ $target, initalState }) {
    const $list = document.createElement('div')
    $target.appendChild($list)

    this.state = initalState

    this.setState = async () => {
        const documentList = await request(``)
        this.state = documentList
        this.render()
    }

    this.createTreeView = (data) => {
        let str = ''
        for (const key in data) {
            if (data[key].documents.length > 0) {
                str += `
                    <li class="dataList">
                        📄 ${data[key].title}
                        <button class="addBtn" data-id="${
                            data[key].id
                        }">➕</button>
                        <button class="delBtn" data-id="${
                            data[key].id
                        }">🗑️</button>
                        <ul>${this.createTreeView(data[key].documents)}</ul>
                    </li>
               `
            } else {
                str += `
                <li class="dataList">
                    📄 ${data[key].title}
                    <button class="addBtn" data-id="${data[key].id}">➕</button>
                    <button class="delBtn" data-id="${data[key].id}">🗑️</button>
                </li>
           `
            }
        }

        return str
    }

    this.render = () => {
        $list.innerHTML = `
        <ul class="documentList">
            ${this.state
                .map(
                    (document) =>
                        `<li class="dataList">📄 ${document.title}
                        <button class="addBtn" data-id="${
                            document.id
                        }">➕</button>
                        <button class="delBtn" data-id="${
                            document.id
                        }">🗑️</button>
                    </li>
                    ${
                        document.documents.length > 0
                            ? `<ul>${this.createTreeView(
                                  document.documents
                              )} </ul>`
                            : ''
                    }
                    
                    
                    `
                )
                .join('')}
        </ul>
    `
    }
    this.render()

    const onDelete = async (id) => {
        await request(`/${id}`, {
            method: 'DELETE',
        })
        this.setState()
    }

    const onUpate = async (id) => {
        await request('', {
            method: 'POST',
            body: JSON.stringify({
                title: '제목없음',
                parent: id,
            }),
        })
        this.setState()
    }
    $list.addEventListener('click', (e) => {
        const classname = e.target.className
        const id = e.target.dataset.id

        if (classname == 'delBtn') {
            onDelete(id)
        } else if (classname == 'addBtn') {
            onUpate(id)
        }
    })
}

export default SideBarList

 

 const onUpate = async (id) => {
        await request('', {
            method: 'POST',
            body: JSON.stringify({
                title: '제목없음',
                parent: id,
            }),
        })
        this.setState()
    }

 

이 함수는 게시글의 자식요소를 생성할때 쓰이는 함수입니다.

$list.addEventListener('click', (e) => {
        const classname = e.target.className
        const id = e.target.dataset.id

        if (classname == 'delBtn') {
            onDelete(id)
        } else if (classname == 'addBtn') {
            onUpate(id)
        }
    })