William Ngan William Ngan - 4 months ago 31
Scala Question

Scala.js: export class constructor with parameters to javascript

Learning scala.js and trying to export a scala.js class to javascript like this:

@JSExport("Pt")
class Pt[T]( points: Seq[T] ) {

@JSExport
def y = points(1)
}


When I tried this in javascript console (Chrome):

new Pt([1,2,3])


The above throws an error: "$c_sjsr_UndefinedBehaviorError ... 1,2,3 is not an instance of scala.collection.immutable.Seq". Not sure how I can pass a Seq as parameter in javascript.

What's the trick to create a class constructors with parameters, so that it can work as both javascript library and scala library? Do I have to use js.Array? (would prefer immutable collection if possible)

I tried @JSExportAll but it doesn't work either:

@JSExportAll
class Pt[T]( points: Seq[T] ) {
def y = points(1)
}


Then in javascript console (Chrome), I cannot even find the constructor function. It throws "ReferenceError: Pt is not defined"

Answer

You have a couple of options:

Use js.Array everywhere

@JSExport
class Pt[T](points: js.Array[T]) {
  def y = points(1)
}

// Scala
val pt = new Pt(js.Array(1,2,3))

// JS
var pt = new Pt([1,2,3])

Make a secondary constructor that takes a js.Array

class Pt[T](points: Seq[T]) {
  @JSExport
  def this(points: js.Array[T]) = this(points.toSeq)

  def y = points(1)
}

// Scala
val pt = new Pt(Seq(1,2,3))

// JS
var pt = new Pt([1,2,3])

Take a variable argument list in the constructor

@JSExport
class Pt[T](points: T*) {
  def y = points(1)
}

// Scala
val pt1 = new Pt(1,2,3)
val pt2 = new Pt(seq: _*)

// JS
var pt = new Pt(1,2,3)