I have fetched some data from a URL and after that I have generated an HTML template for each item of received data using a forEach
loop. After creating the HTML template for all the elements in response data I have assigned that to document.body.innerHTML
. So it displays all elements with my HTML template.
The response has 30 objects and each object has a link (clone_url
) with other information. I have generated HTML elements for those 30 objects using my HTML template, each has a name, profile Avatar and button to copy the specific link I have mentioned. I want to copy that link into the clipboard when user click the copy button.
Therefore, I want to add event listeners to the buttons. That is where I have been struggling because I have no idea how can I do that. Because I have to access each component and also I want to access related response object to get the link.
const url = "https://api.github.com/users/shrutikapoor08/repos";
fetch(url)
.then((response) => response.json())
.then((users) => {
console.log(users);
let htmlText = "";
users.forEach((i) => {
htmlText += `
<div class="repo-container">
<p class="repo-title">${i.name}</p>
<div class="repo-owner">
<img
src="${i.owner.avatar_url}"
alt="avatar"
class="avatar"
/>
<a href="${i.owner.html_url}" class="repo-owner-username">${i.owner.login}</a>
</div>
<div class="link-container">
<button class="repo-link-btn">Copy</button>
<p class="tooltip">Link Coppied</p>
</div>
</div>
`;
});
document.body.innerHTML = htmlText;
});
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Roboto", sans-serif;
}
.repo-container {
background-color: rgb(255, 253, 251);
border: 1px solid rgb(226, 226, 226);
padding: 15px;
width: 250px;
margin: 10px;
}
.repo-title {
font-weight: bold;
margin-bottom: 10px;
}
.repo-owner {
display: flex;
align-items: center;
}
.avatar {
width: 30px;
height: 30px;
border-radius: 50%;
margin-right: 20px;
}
.repo-owner-username {
font-size: 0.8rem;
text-decoration: none;
}
.tooltip {
background-color: rgba(0, 0, 0, 0.7);
width: fit-content;
padding: 4px 10px;
border-radius: 10px;
font-size: 0.75rem;
color: white;
opacity: 0;
transition: transform 0.3s ease, opacity 0.3s ease;
pointer-events: none;
}
.tooltip.active {
opacity: 1;
transform: translateY(-10px);
}
.link-container {
display: flex;
}
.repo-link-btn {
margin: 10px 0px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./style.css" />
<title>Document</title>
</head>
<body>
<script src="./app.js"></script>
</body>
</html>
This is the code I want to add with each button.
document.querySelector(".repo-link-btn").addEventListener("click", async () => {
const text = "";
await navigator.clipboard.writeText(text);
document.querySelector(".tooltip").classList.add("active");
setTimeout(() => {
document.querySelector(".tooltip").classList.remove("active");
}, 500);
});
const text
should be equal to the response data objects URL. I have to access that data as well. What is the good practice for solving this problem?