Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typescript for loop over HTMLCollection

Tags:

typescript

I want to iterate over the results of

document.getElementsByTagName("...");

It returns an HTMLCollection, not an array. So I can't simply use forEach. The following is possible but doesn't look very nice:

let elements = document.getElementsByTagName("...");
for (var i = 0, m = elements.length; i < m; i++) {
    let element = elements[i];
}

For javascript, there exists pretty much the exact same question: For loop for HTMLCollection elements

And apparently, with the latest updates, modern browsers support:

var list = document.getElementsByClassName("events");
for (let item of list) {
    log(item.id);
}

But the typescript compiler complains:

error TS2495: Type 'NodeListOf<HTMLParagraphElement>' is not an array type or a string type.

It still transpiles to proper Javascript though. It's even aware of what I'm doing here and doesn't just copy over the sourcecode. The compiled output is this:

var elements = main_div.getElementsByTagName("p");
for (var _i = 0, elements_1 = elements; _i < elements_1.length; _i++) {
    var element = elements_1[_i];
}

This is great, since the generated code will be supported even on older browsers. But I would like to get rid of the error message.

My compilerOptions are this:

{
    "compilerOptions": {

        "module": "commonjs",
        "target": "es5",
        "sourceMap": true,
        "rootDir": "src",
        "lib": [
            "es2015",
            "dom"
        ]
    }
}

I did try to edit my lib options. This specific feature was a part of ES6 and has been reworked a few times. So I tested the various ecmascript versions in lib but couldn't find a working setup.

like image 666
lhk Avatar asked Nov 01 '18 09:11

lhk


People also ask

Can you loop through HTMLCollection?

There are 3 methods that can be used to properly loop through an HTMLCollection. Method 1: Using the for/of loop: The for/of loop is used to loop over values of an iterable object. This includes arrays, strings, nodeLists, and HTMLCollections. The syntax of this loop is similar to the for/in loop.

What is the difference between HTMLCollection and NodeList?

An HTMLCollection is a collection of document elements. A NodeList is a collection of document nodes (element nodes, attribute nodes, and text nodes). HTMLCollection items can be accessed by their name, id, or index number. NodeList items can only be accessed by their index number.

How do you iterate over elements in HTML?

To iterate over the selected elements, you can use forEach() method (supported by most modern web browsers, not IE) or just use the plain old for-loop.

How do I access HTMLCollection array?

An HTMLCollection is an array-like collection (list) of HTML elements. The elements in a collection can be accessed by index (starts at 0). The length Property returns the number of elements in the collection.


2 Answers

You can convert it to an array if you want to use forEach

const elements: Element[] = Array.from(document.getElementsByTagName("..."));
elements.forEach((el: Element) => {
    // do something
})
like image 135
Bill Avatar answered Sep 22 '22 08:09

Bill


The typescript compiler supports this after specifying an extra flag, downlevelIteration:

{
    "compilerOptions": {
        "target": "es5",
        "downlevelIteration": true
    }
}

However, this will not only remove the error, it will also change the compiler output. This input typescript:

function compileTest(){
  let elements = document.getElementsByTagName("p");
  for(let element of elements){
    console.log(element);
  }
}

is compiled to this javascript:

function compileTest() {
    var e_1, _a;
    var elements = document.getElementsByTagName("p");
    try {
        for (var elements_1 = __values(elements), elements_1_1 = elements_1.next(); !elements_1_1.done; elements_1_1 = elements_1.next()) {
            var element = elements_1_1.value;
            console.log(element);
        }
    }
    catch (e_1_1) { e_1 = { error: e_1_1 }; }
    finally {
        try {
            if (elements_1_1 && !elements_1_1.done && (_a = elements_1.return)) _a.call(elements_1);
        }
        finally { if (e_1) throw e_1.error; }
    }
}
like image 44
lhk Avatar answered Sep 20 '22 08:09

lhk