1

I'm trying to dynamically create cards using a db.json, and add - delete, edit, add new features. However, since every card has its own delete button, I'm struggling to attach them to their corresponding cards. Also when trying to log out all the cards, all delete buttons or other dynamically created elements they return empty arrows.

Here's the code:

import axios from 'axios';

const mainWrapper  = document.querySelector('.js-main-wrapper') as HTMLDivElement


type Card = {
  id: number,
  title: string,
  image: string,
  text: string
}


const getData = (data: Card[]) => {
  
  data.forEach(obj => {

    //CARD
    const card = document.createElement("div");
    card.classList.add("card");
    card.classList.add("js-card");
    mainWrapper.appendChild(card);
  
    //IMG-SECTION
    const imgSection = document.createElement("div");
    imgSection.classList.add("img__section");
    card.appendChild(imgSection);
  
    //TEXT-SECTION
    const txtSection = document.createElement("div");
    txtSection.classList.add("text__section");
    card.appendChild(txtSection);
  
    //BUTTON SECTION
    const btnSection = document.createElement("div");
    btnSection.classList.add("btn__section");
    card.appendChild(btnSection);
  
    //IMAGE
    const image = document.createElement("img") as HTMLImageElement
    image.classList.add("image");
    image.src = `${obj.image}`
    imgSection.appendChild(image);
    
    //TITLE
    const title = document.createElement("h4");
    title.classList.add("title");
    title.innerHTML = `${obj.title}`;
    txtSection.appendChild(title);
    
    //TEXT
    const text = document.createElement("p");
    text.classList.add("text");
    text.innerHTML = `${obj.text}`;
    txtSection.appendChild(text);
  
    //EDIT BUTTON
    const editBtn = document.createElement("button");
    editBtn.classList.add("edit__btn");
    editBtn.classList.add("js-edit");
    editBtn.innerHTML = "EDIT";
    btnSection.appendChild(editBtn);
  
    //DELETE BUTTON
    const deleteBtn = document.createElement("button");
    deleteBtn.classList.add("delete__btn");
    deleteBtn.classList.add(`js-delete`);
    deleteBtn.innerHTML = "DELETE";
    btnSection.appendChild(deleteBtn);
    });

}

axios.get<Card[]>('http://localhost:3004/cards').then(({ data }) => {
  getData(data)

})


let deleteButtons = document.querySelectorAll<HTMLButtonElement>(`.js-delete`)
let editButtons = document.querySelectorAll<HTMLButtonElement>('.js-edit')
let cards = document.querySelectorAll('.js-card')
const addTitle = document.querySelector('.js-add-title') as HTMLInputElement
const addText = document.querySelector('.js-add-text') as HTMLInputElement
const addBtn = document.querySelector('.js-add-btn')

for (let i = 0; i < deleteButtons.length; i++) {
  deleteButtons[i].addEventListener('click', () => {
    axios.delete<Card[]>(`http://localhost:3004/cards/${i +1}`).then(({ data }) => {
      getData(data)
    });
  });
}



//ADD NEW
addBtn?.addEventListener('click', () => {
  axios.post<Card[]>('http://localhost:3004/cards', {
    title: addTitle.value,
    text: addText.value,
    image: "https://picsum.photos/200",
  }).then(({ data }) => {
     getData(data)
  });
});

HTML

<body>
    <section class="main__section">
        <div class="main__wrapper js-main-wrapper">
        </div>
    </section>
    <section class="input__section">
        <div class="input__wrapper">
            <span>Add new</span>
            <hr>
            <form class="form">
                <label> Title
                    <br>
                    <input type="text" class="input__title js-add-title" required>
                    <br>
                    Text
                    <br>
                    <textarea cols="30" rows="10" class="js-add-text"></textarea>
                    <br>
                    <button class="add__button js-add-btn">Add</button> 
                </label>
            </form>

        </div>
    </section>
    <script src="/scripts.js"></script>
</body>

db.json

{
  "cards": [
    {
      "id": 1,
      "title": "Title 1",
      "image": "https://picsum.photos/200",
      "text": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic"
    },
    {
      "id": 2,
      "title": "Title 2",
      "image": "https://picsum.photos/200",
      "text": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic"
    },
    {
      "id": 3,
      "title": "Title 3",
      "image": "https://picsum.photos/200",
      "text": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic"
    },
    {
      "id": 4,
      "title": "Title 4",
      "image": "https://picsum.photos/200",
      "text": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic"
    },
    {
      "title": "wrwrwrwr",
      "text": "rwrwrwr",
      "image": "https://picsum.photos/200",
      "id": 5
    },
    {
      "title": "",
      "text": "",
      "image": "https://picsum.photos/200",
      "id": 6
    }
  ]
}

Here's the click eventlistener in particular:

for (let i = 0; i < deleteButtons.length; i++) {
  deleteButtons[i].addEventListener('click', () => {
    axios.delete<Card[]>(`http://localhost:3004/cards/${i +1}`).then(({ data }) => {
      getData(data)
    });
  });
}
Zixxy7
  • 71
  • 4

1 Answers1

0

Have you have tested the API endpoint? I think that could be the issue. I switched out your API call to localhost with a call to 'https://jsonplaceholder.typicode.com/users', and your code that creates the card UI worked just fine.

axios.get("https://jsonplaceholder.typicode.com/users").then(({ data }) => {
  getData(data);
});

Also, I had to modify the type:

type Card = {
  id: string;
  name: string;
  username: string;
  email: string;
};

Hope this helps.

RyanL33
  • 1
  • 4