Kotlin-JS interop - using language constructs

686 Views Asked by At

I have a js interop function which is using the for in construct to iterate over the input elements, but it's throwing error at runtime.

native("document")
val ndoc: dynamic = noImpl

fun jsInterOp() {
    js("console.log('JS inling from kotlin')")

    val ies = ndoc.getElementsByTagName("input")
    for (e in ies) {
      console.log("Input element ID: ${e.id}")
    } 
}

Getting the following js error

Uncaught TypeError: r.iterator is not a functionKotlin.defineRootPackage.kotlin.Kotlin.definePackage.js.Kotlin.definePackage.iterator_s8jyvl$ @ kotlin.js:2538

Any suggestions on how to fix this one?

Kotlin : M12

The generated js code for the function is,

    jsInterOp: function () {
      var tmp$0;
      console.log('JS inling from kotlin');
      var ies = document.getElementsByTagName('input');
      tmp$0 = Kotlin.modules['stdlib'].kotlin.js.iterator_s8jyvl$(ies);
      while (tmp$0.hasNext()) {
        var e = tmp$0.next();
        console.log('Input element ID: ' + e.id);
      }
    },
2

There are 2 best solutions below

2
On

Kotlin for-loop uses a lot of internal magic.forEach() is more straightforward on JS. Try this:

ies.iterator().forEach { ... }

It seems to be a bug in Kotlin M12, because I was unable to do a for-loop even on simple a list.

for(i in listOf(1, 2));  // TranslationInternalException

Also

I am not sure what is that document that you use here, but you may like the standard API:

import kotlin.browser.document
val ies = document.getElementsByTagName("input")
3
On

forEach didn't work because it's an Array function in JS, but getElementsByTagName returns HTMLCollection . So i changed the kotlin code to use the traditional for loop which iterate over this collection and is work as expected.

 val ies = ndoc.getElementsByTagName("input")
 for (i in 0..(ies.length as Int) - 1) {
    console.log("InputElement-${i} : ${ies[i].id}")
 }