Reputation: 3
I'm trying to move individual li elements from one ul to another when a checkbox is selected.
Full code can be found here:http://jsfiddle.net/8f27L0q3/1/
My function that moves the li item can be found below.
ul.addEventListener('change', (e) => {
const checkbox = e.target;
const checked = checkbox.checked;
const listItem = e.target.parentNode.parentNode;
const completedItems =
document.querySelector('.completedItems');
const label = document.querySelector('.completedLabel');
if (checked) {
completedItems.appendChild(listItem);
label.style.display = 'none';
}
});
Once the li is moved to the other ul, the child span containing a label and checkbox disappear. This functionality works when the first child li moves but doesn't work when a li after the first child is moved. Also the first li's span disappears and therefore cannot be moved to the other ul
Upvotes: 0
Views: 62
Reputation: 4998
would you mind reconsidering your strategy in solving this case? It is recommended to work with data such as arrays and objects instead of DOM nodes.
Please consider this example
const form = document.forms.form;
const todoList = document.querySelector('#todoList');
const completedList = document.querySelector('#completedList');
const tasks = [];
form.addEventListener('submit', handleSubmit, true);
todoList.addEventListener('change', handleInputChange, true);
function handleSubmit(event) {
event.preventDefault();
const task = this.task;
if (task.value === '') {
return;
}
const item = createTask(task.value);
tasks.push(item);
task.value = '';
syncTodoList();
}
function handleInputChange(event) {
const target = event.target;
if (target.nodeName === 'INPUT') {
const id = event.target.id;
const task = tasks.find(task => task.id === parseInt(id, 10));
task.status = 'completed';
syncTodoList();
syncCompletedList();
}
}
function createTask(task) {
return {
id: Date.now(),
text: task,
status: 'todo'
};
}
function syncTodoList() {
const todos = tasks
.filter(task => task.status === 'todo')
.map(task => `<li>${task.text} <input type="checkbox" id="${task.id}"></li>`)
.join('');
todoList.innerHTML = todos;
}
function syncCompletedList() {
const completeds = tasks
.filter(task => task.status === 'completed')
.map(task => `<li>${task.text}</li>`)
.join('');
completedList.innerHTML = completeds;
}
<form name="form">
<input id="task">
<button>Send</button>
</form>
<p>Todo</p>
<ul id="todoList"></ul>
<p>Completed</p>
<ul id="completedList"></ul>
Upvotes: 0
Reputation: 186
Looks like you are asking for the .completedLabel
selector globally when you just need to search for it inside the item that was clicked.
May reducing the scope of the query selector to the element you are storing in listItem may work. Here is an example:
const label = listItem.querySelector('.completedLabel');
That way it works reusing your sample code:
//move li item to completed list when checkbox selected
ul.addEventListener('change', (e) => {
const checkbox = e.target;
const checked = checkbox.checked;
const listItem = e.target.parentNode.parentNode;
const completedItems = document.querySelector('.completedItems');
const label = listItem.querySelector('.completedLabel');
if (checked) {
completedItems.appendChild(listItem);
label.style.display = 'none';
}
});
However the implementation can be tweaked a little bit more.
Upvotes: 1