0

I am a beginner on JavaScript, looking for a explanation on accessing to an object property that does not exist on an DOM element.

I am working on a todo apps. Below is my current code but it is not completed. There's an empty todosArray, then todoObj with two properties (todo, completed) will be added to the array when users add an item.

Later in the code where item can be removed or crossed out if users clicked on the item. In this click addEventListener, a variable clickedEl is created in the else if statement and it accessed/copied(?) the completed property from the todosArray. This is where I do not understand.

How is the clickedEl has access to the completed property? What is actually happening here?

// Variables 
const form = document.querySelector('form');
const formInput = document.querySelector('input[type=text]');
const ul = document.querySelector('ul');
const addBtn = document.querySelector('input[type=submit]');
const todosArray = [];

// Add item 
function addTodo(item) {
    const todoObj = {
        todo: item,
        completed: false
    };

    todosArray.push(todoObj);
    
    // Save to localStorage
    localStorage.setItem('todosArray', JSON.stringify(todosArray));
    
    formInput.value = '';
};

// Add task to todo list
form.addEventListener('submit', function (e) {
    e.preventDefault();
    
    if (formInput.value === '') {
        alert('Please add a task.');
    }
    else {
        const newLi = document.createElement('li');
        newLi.innerHTML = formInput.value;
        ul.append(newLi);
        const removeBtn = document.createElement('button');
        newLi.append(removeBtn);
        removeBtn.innerHTML = 'Remove';

        addTodo(formInput.value);
    };
});

// Remove/complete list item
ul.addEventListener('click', function (e) {
    if (e.target.textContent === 'Remove') {
        e.target.parentElement.remove();
    }
    else if (e.target.tagName === 'LI') {

        const clickedEl = e.target //li
        //console.log('clickedEl: ', clickedEl)
        if (clickedEl.completed === true) {
            clickedEl.style.textDecoration = 'none';
        }
        else {
            
            clickedEl.style.textDecoration = 'line-through';
            clickedEl.completed = true;
        }
    }
});

// Retrieve from localStorage
if (localStorage.getItem('todosArray')) {
    const todosList = JSON.parse(localStorage.getItem('todosArray'));

    for (let i = 0; i < todosList.length; i++){
        const newLi = document.createElement('li');
        newLi.textContent = todosList[i].todo;
        ul.append(newLi);
        const removeBtn = document.createElement('button');
        newLi.append(removeBtn);
        removeBtn.textContent = 'Remove';

        console.log(todosList[i]);
    }
}

I talked to a mentor but I was not able to understand his explanation. Also, googled quit a bit, but most results are related to property accessors.

2
  • clickedEl.completed has no relation to the completed property in todosList.
    – Barmar
    Commented Feb 29 at 23:52
  • There's nothing in your code that does anything to todosList when you click on the item.
    – Barmar
    Commented Feb 29 at 23:54

1 Answer 1

0

DOM elements are not the same as plain JavaScript objects, meaning they don't have all the properties and methods that regular JavaScript objects have.

When you access e.target, you're getting a reference to the DOM element that triggered the event. It is a plain HTML element, does not have properties like completed.

else if (e.target.tagName === 'LI') {
    const clickedEl = e.target; // This is a reference to the <li> element
    if (clickedEl.completed === true) { // Trying to access completed property
        clickedEl.style.textDecoration = 'none';
    } else {
        clickedEl.style.textDecoration = 'line-through';
        clickedEl.completed = true; // Assigning a new property completed to the DOM element
    }
}

In this part, clickedEl refers to the list element that was clicked. There is no completed property defined on a regular DOM element. In JavaScript, you can dynamically add properties to objects, and this is what's happening below.

clickedEl.completed = true;

You're adding a new property completed to the list (li) element. This is why clickedEl.completed works, even though it's not a built-in property of DOM elements.

Not the answer you're looking for? Browse other questions tagged or ask your own question.