Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialSteve Gallant
14,943 Pointsinteracting with HTML retreived from localStorage (via JSON)
Hello there, I've managed to get most of the enhancements for this RSVP app done on my own, but having trouble with localStorage. I'm able to save the ul using JSON and then pull it back up when the page is re-loaded. However, the loaded LI's are not interactive, i.e. there don't appear to be any eventListeners active on their child elements (checkbox, buttons, etc). Furthermore, adding a new invitee via the main input field, it doesn't appear in the ul with the pre-loaded invitees from localStorage.
I think I'm almost there, any tips would be appreciated. Thanks! Steve
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>RSVP App</title>
<link href="https://fonts.googleapis.com/css?family=Courgette" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato:400,700" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<div class="wrapper">
<header>
<h1>RSVP</h1>
<p>A Treehouse App</p>
<form id="registrar">
<input type="text" name="name" placeholder="Invite Someone">
<button type="submit" name="submit" value="submit">Submit</button>
</form>
</header>
<div class="main">
<h2>Invitees</h2>
<ul id="invitedList"></ul>
</div>
</div>
<script type="text/javascript" src="app.js"></script>
</body>
</html>
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('registrar');
const input = form.querySelector('input');
const mainDiv = document.querySelector('.main');
const ul = document.getElementById('invitedList');
const div = document.createElement('div');
const filterLabel = document.createElement('label');
const filterCheckBox = document.createElement('input');
filterLabel.textContent = "Hide those who haven't responded";
filterCheckBox.type = 'checkbox';
div.appendChild(filterLabel);
div.appendChild(filterCheckBox);
mainDiv.insertBefore(div, ul);
if (localStorage.invitees) {
ul.outerHTML = JSON.parse(localStorage.invitees);
}
filterCheckBox.addEventListener('change', (e) => {
const isChecked = e.target.checked;
const lis = ul.children;
if(isChecked) {
for (let i = 0; i < lis.length; i += 1) {
let li = lis[i];
if (li.className === 'responded') {
li.style.display = '';
// Hide the checkbox and label for confirmed invitees when
// filter is activated
li.getElementsByTagName('label')[0].style.display = 'none';
// console.log(li.getElementsByTagName('label')[0]);
} else {
li.style.display = 'none';
}
}
} else {
for (let i = 0; i < lis.length; i += 1) {
let li = lis[i];
li.style.display = '';
// Show checkbox and label again when filter is removed
li.getElementsByTagName('label')[0].style.display = '';
}
}
});
function createLI(text) {
function createElement(elementName, property, value) {
const element = document.createElement(elementName);
element[property] = value;
return element;
}
function appendToLI(elementName, property, value) {
const element = createElement(elementName, property, value);
li.appendChild(element);
return element;
}
const li = document.createElement('li');
appendToLI('span', 'textContent', text);
appendToLI('label', 'textContent', 'Confirm?')
.appendChild(createElement('input', 'type', 'checkbox'));
appendToLI('button', 'textContent', 'edit');
appendToLI('button', 'textContent', 'remove');
return li;
}
form.addEventListener('submit', (e) => {
e.preventDefault();
const text = input.value;
// disallow duplicate names for invitees
let duplicate = false;
if (ul.children.length > 0) {
for (i = 0; i < ul.children.length; i++) {
if (text.toLowerCase() === ul.children[i].firstElementChild.textContent.toLowerCase()) {
duplicate = true;
console.log(duplicate);
}
}
}
// check for empty string and disallow
if (text === '') {
alert('Please enter a valid name');
} else if (duplicate) { // check for duplicate names
alert("Duplicate names not allowed");
duplicate = false;
} else {
input.value = '';
const li = createLI(text);
ul.appendChild(li);
// store ul in localStorage
console.log(ul.outerHTML);
localStorage.setItem('invitees', JSON.stringify(ul.outerHTML));
}
});
ul.addEventListener('change', (e) => {
const checkbox = event.target;
const checked = checkbox.checked;
const listItem = checkbox.parentNode.parentNode;
const label = checkbox.parentNode;
if (checked) {
listItem.className = 'responded';
label.childNodes[0].nodeValue = 'Confirmed';
} else {
listItem.className = '';
label.childNodes[0].nodeValue = 'Confirm?';
}
});
ul.addEventListener('click', (e) => {
if (e.target.tagName === 'BUTTON') {
const button = e.target;
const li = button.parentNode;
const ul = li.parentNode;
const action = button.textContent;
const nameActions = {
remove: () => {
ul.removeChild(li);
},
edit: () => {
const span = li.firstElementChild;
const input = document.createElement('input');
input.type = 'text';
input.value = span.textContent;
li.insertBefore(input, span);
li.removeChild(span);
button.textContent = 'save';
},
save: () => {
const input = li.firstElementChild;
const span = document.createElement('span');
span.textContent = input.value;
li.insertBefore(span, input);
li.removeChild(input);
button.textContent = 'edit';
}
};
// select and run action in button's name
nameActions[action]();
}
});
});
1 Answer
Jay Reyes
Python Web Development Techdegree Student 15,937 PointsI'm also experiencing this issue. I'm able to save the invitees and they get loaded.
The problem is that the buttons for the any list item is not interactive.
e: they became interactive for me I just forgot the "()" in nameActionsaction
Steve Gallant
14,943 PointsSteve Gallant
14,943 PointsHi Jay, I'm unclear if you are saying you found the error in my code above? If so, could you please be more specific? I do have the closed parens when calling nameActions...
thanks! Steve