I have a Scala.js application using Udash . The application is using some Bootstrap extensions, which directly manipulate HTML DOM. I would like to traverse this DOM and add some more handlers to it (eventually I would like the handlers to implement Udash binding ). My trouble is the only way I can do this is by inserting a script
tag, which expects me to provide a plain Javascript code.
Is there some way I could call by Scala.js code from this Javascript? Normally I would export a global function and pass any necessary parameters to it, however I do not see any clean way how to pass this
, the only way I can think of is using a global variable, which look super ugly to me. Is there anything like local exports, or some other way how to create a JavaScript code I could pass into script
which would be able to access Scala.js constructs?
My current code looks like this:
// somewhere in class ExtTable .. in the `render` method
div(
p(id := componentId, "Html constructed here"),
script {
ExtTable.callback = { e =>
println(s"JS Callback for $e on $this")
}
//language=JavaScript
s"""
// I would like to implement this in Scala.js instead
var t = $$('#${componentId.toString}');
t.bootstrapTable();
t.find("tr td:first-of-type").each(function(i,e){
ExtTable.callback(e);
})
"""
}
).render
@js.annotation.JSExportTopLevel("ExtTable")
object ExtTable {
@js.annotation.JSExport
var callback: js.Function1[Element, Unit] = _
}
TRANSLATE YOUR SNIPPED TO SCALAJS
You need to use some jquery wrapper library. Udash has its own... I'm using oldest one ( here ) (example below).
import org.scalajs.jquery.jQuery
import org.scalajs.dom.Element
import scala.scalajs.js
@js.annotation.JSExportTopLevel("ExtTable")
object ExtTable {
@js.annotation.JSExport
var callback: js.ThisFunction0[Element, Unit] = _ //look first argument is what `this` in js means
}
var t = jQuery("#"+componentId.toString);
t.asInstanceOf[js.Dynamic].bootstrapTable(); //to call function that is not known statically!
t.find("tr td:first-of-type").each( { (e: Element) =>
ExtTable.callback(e)
})
this
in body you need to use js.ThisFunction
(find more here ). In above example .each(...)
takes ThisFunction1[Element,_]
and it means this
from javascript will be our first argument ( e:Element
in code above). As you can see it is inferred from normal scala closure notation ( {(e: Element) => ...}
)..asInstanceOf[js.Dynamic]
part is necessary here to call function on jquery object that comes from jquery addon. js.Dynamic
is special type that you can call any method on it, and compiler will just translate it to same call on js site ( doc ). You can understand it as "Trust me... there will be such method on runtime". Creator of jquery facade cannot assume what addons you would use, and you need to create your own facades or use it dynamically as shown above. CALLING FUNCTION ON ELEMENT CREATED BY SCALATAGS
You can also create Modifier that will call your code when object is created. Be awared that it will be called before element is injected into dom :
import scalatags.JsDom.all._
import org.scalajs.jquery.jQuery
import org.scalajs.dom.Element
import scala.scalajs.js
import scalatags.JsDom.Modifier
val bootstrapTable:Modifier = new Modifier {
override def applyTo(t0: Element): Unit = {
val t = jQuery(t0)
t.asInstanceOf[js.Dynamic].bootstrapTable()
t.find("tr td:first-of-type").each(i => {
ExtTable.callback(e)
})
}
//in scala 2.12 you can write it simpler
val bootstrapTable2:Modifier = (t0: Element) => {
val t = jQuery(t0)
...
}
div(p(
id := "componentId",
"Html constructed here",
//use modifier here,
bootstrapTable,
//you can create new anonymous modifier here:
new scalatags.JsDom.Modifier {
override def applyTo(t: Element): Unit = println("ex1:" + t.outerHTML)
}
//in scala 2.12+ you can do it like that (same semantic as above example)
(e:Element) => println("ex2:" +e.outerHTML)
)).render
jQuery("#" + componentId)
because you have access to Element ( jQuery(t0)
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.