IamJB
IamJB

Reputation: 33

Can't access new elements after Ajax call (Vanilla JS)

I have an ajax call that is populating a list with items, but after the call is completed I can't access the list items in the DOM to add eventlisteners, console.log outputs an empty nodeList.

My HTML:

<ul class="list"></ul>

My JS file:

let list = document.querySelector('.list'),
listitem = document.querySelectorAll('.list-item'),
content;

function showItems() {

    let url = 'https://swapi.co/api/people';
    fetch(url)
    .then(function(response) {
        return response.json();
    }).then(function(data) {
        let results = data.results;
        results.forEach(item => {
            content = `<li class="list-item"><a href="#">${item.name}</a></li>`;
            list.innerHTML += content;
        });

        //This displays the entire content
        console.log(list);

        //This doens't find the child elements
        console.log(listitem);

    }).catch(function(err) {
        console.log(err);
    });
}

showItems();

The weird thing is if I console.log the list it displays the newly created elements, but if I try to console.log the list-item directly, the result is NodeList(0) and I believe that if the call wasn't finished the complete list shouldn't show the list items as well.

There is a test here: https://jsfiddle.net/magutj8L/1/

NOTE: I don't want to use JQuery.

Upvotes: 3

Views: 2880

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370809

querySelectorAll returns a static NodeList. If you call document.querySelectorAll, it will return whatever matching elements exist at the time you called it - it won't automatically update to include new elements. (This is arguably more intuitive than were the situation reversed - you don't really want a variable to mutate itself while you're iterating over it, this is a frequent source of bugs)

You should select the elements again after the list is populated:

const newListitems = document.querySelectorAll('.list-item');
console.log(newListitems);

Note that getElementsByClassName is an option, which will return a live HTMLCollection - the new elements added will be present in the collection, without selecting them again:

listitem = document.getElementsByClassName('list-item')

But, IMO, live collections are unintuitive, so I wouldn't recommend using logic that depends on it.

Upvotes: 1

Related Questions