I am working on my first personal project and I am almost finished, but I am struggling to get some buttons to work. My project is one where bookmarks can be saved, and there is a column for bookmarks that are favorites, and a column for the other saved bookmarks. These buttons each correspond to an item retrieved from the database (I'm using Firestore for my database, but for this post I have modified it to eliminate the need for Firestore), and hence are not hardcoded into the html file. When a new bookmark is saved, it has a name (such as "Reddit"), a url ("www.reddit.com"), and a boolean for its favorite status (true if it is a favorite, false if otherwise). I want each bookmark to have an associated button which can be clicked to move the bookmark to the other column. I am stuck on how to add an event listener to each item in the database that only modifies the data from that one item. The code is below (there is more explanation at the bottom.
The full code can be found here (includes everything you need to run the program in full): https://github.com/matt-manning/Bookmarker
Here is a minimized version (still sufficient enough to be used on its own):
const bookmarkList = document.querySelector('#other-list');
const favoriteList = document.querySelector('#favorite-list');
const form = document.querySelector('#add-bookmark');
function start() {
const db = [
{website: 'Reddit', url: 'www.reddit.com', favorite: true},
{website: 'Google', url: 'www.google.com', favorite: false},
{website: 'Netflix', url: 'www.netflix.com', favorite: true},
{website: 'YouTube', url: 'www.youtube.com', favorite: false}
];
const bookmarkData = setupBookmarks(db);
registerBookmarkEventListeners(db, bookmarkData);
}
const setupBookmarks = (data) => {
let favoritesHTML, bookmarksHTML = '';
const bookmarkData = [];
if (data && data.length) {
data.forEach(doc => {
const bookmarkId = Math.floor(Math.random() * 10000000);
const bookmark = doc;
if (bookmark.favorite) {
favoritesHTML += bookmarkHTML(bookmark, bookmarkId);
} else {
bookmarksHTML += bookmarkHTML(bookmark, bookmarkId);
}
bookmarkData.push({bookmark, bookmarkId});
})
}
favoriteList.innerHTML = favoritesHTML;
bookmarkList.innerHTML = bookmarksHTML;
return bookmarkData;
}
const bookmarkHTML = (bookmark, bookmarkId) => {
let html = '';
// cut for minimizing; here is a potentially relevant snippet. Full code can be found in the github link above.
const li =
`<li>
<button class='btn-flat waves-light btn-small right listener' id='${bookmarkId}'>
<i class='material-icons left'>compare_arrows</i>switch</button>
<li>`;
html += li;
return html;
}
My problems lie in the registerBookmarkEventListeners function. What I want this function to do is add an event listener to a button on each bookmark, and when the button is clicked, the 'favorite' boolean in said bookmark changes to the opposite, which would then make the bookmark switch to the other column.
Here are a couple attempts I have made (more attempts can be found in the github link):
const registerBookmarkEventListeners = (data, bookmarkData) => {
document.querySelectorAll('.listener').forEach(elem => {
elem.addEventListener('click', e => {
e.preventDefault();
const bookmark = elem;
if (bookmark.favorite) {
bookmark.favorite = false;
} else {
bookmark.favorite = true;
}
})
})
}
const registerBookmarkEventListeners = (data, bookmarkData) => {
const {bookmark, bookmarkId} = bookmarkData;
bookmarkData.forEach(item => {
const btnElement = document.querySelector(`#${bookmarkId}`);
btnElement.addEventListener('click', e => {
e.preventDefault();
if (bookmark.favorite) {
bookmark.favorite = false;
} else {
bookmark.favorite = true;
}
})
})
}
I understand why my attempts above don't work. The first one doesn't even use either of the parameters given with the data from the database. The second one uses bookmarkId, but it doesn't 'connect' (if that is the right word) to the data it is supposed to be modifying. I'm struggling to find out how to make this addEventListener work.
So, how do I add event listeners to buttons through a loop which each directly modify a different part of the data?
Thanks for any help.
Also, for completeness, here is the relevant HTML needed to run the program:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bookmarker</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
<div class='row logged-in show-none'>
<div class="col s6">
<h5>Favorites</h5>
<ul id='favorite-list'></ul>
</div>
<div class="col s6">
<h5>Bookmarks</h5>
<ul id='other-list'></ul>
</div>
</div>
<script src='script.js'></script>
</body>
</html>