Umar
Umar

Reputation: 113

find is not a function

I can't seem to understand why I'm getting this error. All I want to do is check if the array has an item with the class of 'active'. Using Find seems correct as it only needs to return 1 value. Here is my code:

const tabWrapper = document.querySelector('.nav-tabs');
const tabs = tabWrapper.getElementsByTagName('li');
const indicator = document.querySelector('.slider-indicator');
const tabWidth = tabWrapper.offsetWidth;
let startPos = tabWrapper.getBoundingClientRect().left;

console.log(tabs);

function checkActive(item) {
    console.log(item.classList.contains('active'));
}

tabs.find(checkActive);

Upvotes: 1

Views: 3999

Answers (3)

Scott Marcus
Scott Marcus

Reputation: 65806

.getElementsByTagName() returns a "live" node list, which is an "array-like" object, but not an actual array (it doesn't inherit from Array.prototype). As such, it won't implement all the methods that a real array does.

If you want to use the elements within that node list in an array structure, you must convert that node list into an actual array, which is done like this:

const tabs = Array.prototype.slice.call(tabWrapper.getElementsByTagName('li'));

Now, back to the "live" node list concept...A live node list is one that updates its contents upon each access of the variable referencing it. This means that (in your case) every single time you use tabs in your code, the entire document is re-scanned for all li elements. There are only a few use cases for needing one and if you don't, you can possibly improve the performance of your code substantially by not using one. .querySelectorAll() is a more modern DOM API that returns a static node list, which is generally preferred.

const tabs = Array.prototype.slice.call(tabWrapper.querySelectorAlll('li'));

Upvotes: 1

Feathercrown
Feathercrown

Reputation: 2591

You need to convert the NodeList into an array.

Your code to select the <li> elements should be fine, I changed it so I could use minimal HTML in the example.

const tabs = document.getElementsByTagName('li');

console.log(tabs);

function checkActive(item) {
    return item.classList.contains('active');
}

console.log("Found anything: " + Boolean(Array.from(tabs).find(checkActive)));
<li class="active">foo</li>
<li class="randomClass">bar</li>

Upvotes: 0

epascarello
epascarello

Reputation: 207511

You might be better off with querySelector or querySelectorAll.

const activeLI = document.querySelector("li.active");
const activeLIs = document.querySelectorAll("li.active");

That will return which will give you the li element(s) with the active class. If you want to use Array methods, you need to convert the collection into an array.

const lis = document.getElementsByTagName('li');
const liArray = Array.from(lis);
console.log(liArray.find) // shows you now have a find method

Upvotes: 0

Related Questions