Dynamic calls to JavaScript in Scala.js - scala

I am wondering how to do dynamic operations in Scala.js. For example, looking at the jQuery example in the tutorial, my understanding is you define the following in scala:
object TutorialApp extends JSApp {
def appendPar(msg: String) = {
jQuery("body").append("<p>" + msg + "</p>")
}
def main(): Unit = {
appendPar("Hello World")
}
}
This is all stuff that is generated statically at compile time. But I didn't see any way I could set the message parameter dynamically (eg read it from a DB).

I don't know about reading it from the DB. That is beyond the scope of this question (or you need to rephrase the question). Maybe an AJAX call or something?
But to read it from, for example, an <input> tag, you'd do something like that:
def main(): Unit = {
val msg = jQuery("#myinput").value()
appendPar(msg)
}
(Although in this case it probably doesn't make any sense in a main method, but that's not the point.)
I mean, msg is just a val (so like a var in JS but immutable). You can fetch it from any dynamic source of information as you like.
Edit:
If you want to access some data generated dynamically by the server when rendering the page, you can do so like this:
First, have your server generate the data as a global var in a <script> tag in the generated HTML. Something like:
<script type="text/javascript">
var mydata = {
msg: "Some text generated dynamically by the server"
}
</script>
Make sure to emit this script tag before the call to the main() function of Scala.js!
Then, from Scala.js, you can access these data with the js.Dynamic interface:
import scala.scalajs.js
val mydata = js.Dynamic.global.mydata
val msg = mydata.msg.asInstanceOf[String]
If your data have always a relatively static structure, it may be useful to declare yourself a facade type for them:
#JSName("mydata")
object MyData extends js.Object {
val msg: String = ???
}
Then you can access it without resorting to the Dynamic API:
val msg = MyData.msg

Adding to (and attempting to generalize) sjrd's answer: To call a javaScriptMethod on an object of a JavaScriptType you first write a type facade for it:
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
#js.native
#JSName("JavaScriptType")
class MyType() extends js.Object {
def javaScriptMethod(someParam: String) = js.native
}
After that, it's a piece of cake to use the JavaScript code using Scala on the client side:
val myObject = new MyType()
myObject.javaScriptMethod("Yippie")
As a concrete example, to use Stack Overflow's Markdown converter Pagedown in your Scala.js application you'd first create the type facade for it:
#js.native
#JSName("Markdown.Converter")
class MarkdownConverter() extends js.Object {
def makeHtml(txtUsingMarkdown: String): String = js.native
}
If you are learning Scala.js using this great tutorial project, you can declare the dependency on Pagedown in Settings.scala like this:
val jsDependencies = Def.setting(Seq(
"org.webjars.bower" % "pagedown" % "1.1.0" / "Markdown.Converter.js",
//...
Then you can simply do
val html = new MarkdownConverter().makeHtml("this is *nice*")
Here's another example where we call a static method of SparkMD5.
We define an object as opposed to the class of the previous example. Also, we can omit the #JSName annotation since our Scala type is eponymous with the JavaScript type:
#js.native
object SparkMD5 extends js.Object {
def hash(str: String, raw: Boolean = false): String = js.native
}

Related

Scala object constructor

I have to create a file loader object and I would like the file to be loaded only once at object creation.
What I did until now is create a trait with a method read that will read file and output a list of String.
trait Loader {
protected val readSource: List[String] = {
Source
.fromInputStream(getClass.getResourceAsStream("filename"), "UTF-8")
.getLines()
.toList
}
def transform(delimeter: String): Vector[C] = {
val lines = readSource
// process the lines
}
}
The trait is implemented by several object, and the transform method can be called multiple times in the client code.
I would like to avoid re reading the file each time the transform method is called and my first solution was to extract the val lines = readSource from the transform method and make a function of it def loadFile = readSource and to create a apply method in my objects to call loadFile like so :
object MyLoader extends Loader {
def apply: List[String] = {
loadFile
}
}
I am wondering if this is the right way to do it. Thank you for your advices.
If you want the resource read once for all, then you should do that in a singleton object, which will be initialized once lazily.
Clients should use that object. "Prefer composition over inheritance" is the mantra.
If you want a mix-in that makes it easy to use the object, you can use "self-types" to constrain clients:
trait HasResource { val resource: R = TheResource }
trait Client { self: HasResource => def getR: R = resource }
This is the "cake pattern" way of making stuff available.

JavaScript object as function parameter

I'm writting a function transpiled with Scala.js that should accept any random JavaScript object.
Ex:
// This has been transpiled using Scala.js
var my_service = new com.myself.Service();
// This is plain JavaScript
var result1 = service({ hello: "yolo" });
var result2 = service({ whatever: "ok", really: { yes: "right", no: "don't" } });
However, I can't find the input type that matches it.
What would be the Scala-function signature to get such a thing?
Could it be used then as a "Scala/JS case class" easily?
Note (if it helps giving a direction for the answers): these objects have, in the real life, an expected schema but it cannot be created as JS object generated from Scala.js since it comes from another consumed service.
Since the objects have an expected schema, its probably easiest to define a facade type:
#js.native
trait Args extends js.Object {
val hello: js.UndefOr[String]
val whatever: js.UndefOr[String]
val really: js.UndefOr[ReallyArgs]
}
#js.native
trait Really extends js.Object {
val yes: String
val no: String
}
def myMethod(args: Args): Unit = {
println(args.hello)
println(args.really.map(_.yes))
}

How do I create "options objects" in Scala.Js?

In idiomatic JavaScript it's common to have a function accept an "options object" as the last parameter. This is where you'd usually put all the option/seldom-used parameters, e.g.
jQuery.ajax({
url: "http://www.example.com/foo",
success: function() {
..
}
})
The current documentation for Scala.JS recommands using a Scala trait to represent the options object, but that leads to a problem when you have to create the options since you cannot pass an anonymous class into JavaScript code.
How can such option objects be created from Scala code?
We recommend the following (if you chose to create facade-types):
trait AjaxOptions extends js.Object {
val url: String = js.native
val success: js.Function0[Unit] = js.native
}
object AjaxOptions {
def apply(url: String, success: js.Function0[Unit]): AjaxOptions = {
js.Dynamic.literal(url = url, success = success).asInstanceOf[AjaxOptions]
}
}
The advantage is that the type-unsafe cast is contained in a single location. Further, if you ever decide to add/remove fields to/from AjaxOptions, you will (hopefully) think of also adapting the companion's apply method. As a result, the typer will inform you where you have to change your invocations (rather than just having the new field set to undefined).
Please refer to What is the suggested way to instantiate a js.Object for API wrappers for more.
Since Scala.js has evolved, I'm amending my answer with the current best practice:
At this point, you should use a trait to describe the options object, like this:
trait AjaxOptions extends js.Object {
var url: String
var success: UndefOr[js.Function0[Unit]] = js.undefined
}
That UndefOr[T] means "this field might contain T, or might be undefined"; note that you are initializing those to js.undefined, so they have a default value.
Then, at the call site, you simply override the values that you need to set:
val ajaxResult = new AjaxOptions {
url = "http://www.example.com/foo"
}
Note the curly braces: you're actually creating an anonymous subclass of AjaxOptions here, that does what you want. Any fields you don't override (such as success above) get left as undefined, so the library will use its default.
Old Answer:
This question is pretty old, but since people are still coming here:
If you have a large and complex options object (as is typical of, say, jQuery UI classes), you may want to build a facade for that using JSOptionBuilder, which is found in the jsext library. JSOptionBuilder isn't quite a panacea, but it's a not-too-much boilerplate mechanism for constructing and using arbitrarily complex options objects.
Here's a method that I've found to work quite well:
val fooOptions = js.Dynamic.literal().asInstanceOf[FooOptions]
fooOptions.url = ...
fooOptions.bar = ...
jsFunc(..., fooOptions)
Of course this assumes that the FooOptions trait has declared the fields as var. If not, you'll have to use
val fooOptions = js.Dynamic.literal(
url = ...,
bar = ...,
)
jsFunc(..., fooOptions)
but that is less type-safe.
If you're declaring your own options trait, you could also add a companion object with an appropriate apply method:
trait FooOptions extends Js.Object {
var foo: js.String = ???
var bar: js.String = ???
}
object FooOptions {
def apply(): FooOptions =
js.Dynamic.literal().asInstanceOf[FooOptions]
}
That'll make calling code a lot prettier:
val fooOptions = FooOptions()
fooOptions.foo = ...
fooOptions.bar = ...
jsFunc(..., fooOptions)

Where to put my database access methods when using a DAO with Slick 2.0?

(This question is based on a very similar previous request for help. With the introduction of a DAO and multiple database drivers, the same problem requires a different approach, and I hope warrants a new SO question.)
I have a class and Slick Table defined like this:
import play.api.db.slick.Profile
case class Foo(title: String, description: String, id: Int = 0)
trait FooComponent extends Profile { this: Profile =>
import profile.simple._
class FooTable(tag: Tag) extends Table[Foo](tag, "FOO") {
def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def title = column[String]("TITLE", O.NotNull)
def description = column[String]("DESCRIPTION")
def * = (title, description, id) <> (Foo.tupled, Foo.unapply)
}
}
And a data access object:
class DAO(override val profile: JdbcProfile) extends FooComponent with Profile {
val foos = TableQuery[FooTable]
}
object current {
val dao = new DAO(DB(play.api.Play.current).driver)
}
This is pretty awesome, because now I can add something like the following to my application.conf:
db.default.driver=org.h2.Driver
db.default.url="jdbc:h2:mem:play"
db.test.driver=org.postgresql.Driver
db.test.user="testuser"
db.test.password=""
db.test.url="jdbc:postgresql:testdb"
... and if I do the following in a Controller:
import models.current.dao._
import models.current.dao.profile.simple._
I have access to my foos TableQuery, and it automagically gets the driver and database url given for db.default in application.conf.
In a similar, but not-quite-as-nice way, I can do the following in my test Specification:
"test Foos" in new WithApplication() {
val dao = new DAO(play.api.db.slick.DB("test").driver)
import dao._ //import all our database Tables
import dao.profile.simple._ //import specific database methods
play.api.db.slick.DB("test").withSession { implicit s: Session =>
println(s.conn.getMetaData.getURL)
println(foos.list)
}
However, what if I want to define a method which can act on a TableQuery[Foo]? Something like this:
def findByTitle(title: String) = foos.filter(_.id === id).list
Problem
What's the correct way of writing the findByTitle method, and where should I put it so that I can:
Call it in a way such that it won't collide with a method of the same name which acts on TableQuery[Bar]. Coming from OO, I feel like I want to do something like foos.findByTitle("someFoo"), but if there's a better way of doing this functional-style, I'm open to suggestions.
Call it from an application Controller such that the query will work with my db.default h2 driver, and from my test Specification so that it will work with my db.test postgres driver.
As an aside, if I can put this in my DAO:
object current {
val dao = new DAO(DB(play.api.Play.current).driver)
}
and then import models.dao.current._ anywhere I want to use this DAO, how can I extend the same form to the following:
object test {
val dao = new DAO(play.api.db.slick.DB("test").driver)
}
If I try to do this, the compiler complains about not having an implicit Application in scope.
I think you need to read up in implicit conversion and implicit parameters in Scala. There are online Scala books available.
When you get an error message about a missing implicit it either means you ran into a failing type-check provided by a library preventing you from doing something wrong, but that's not the case here. Or you simply forgot to make the implicit available. There are two ways to make an implicit available. Either import it into the scope where you get the error message. Or basically defer the lookup to the callsite of your method. Not sure which one is the right one for play. You either need to import the implicit Application from play, or you need turn val dao into a method and request an implicit application in an implicit argument list def dao(implicit app: Application) = .... You can alternatively turn test into a class and request it there.
If you use the play slick plugin it will need a started play application to be able to call code that uses the DB access from that plugin, you can make sure to start a play app in your tests using WithApplication as described in the docs: http://www.playframework.com/documentation/2.3.x/ScalaFunctionalTestingWithSpecs2

"Stable identifer required" error during companion object import

I'm really new to Scala, and I've come across an error I am unable to solve by myself or through internet searches.
I have a Scala class called "GUI" that represents a JFrame along with a companion class. When I try to import the companion class using import GUI._ I get the error "stable identifier required, but GUI.this.GUI() found".
I made an empty class and companion object and the import worked fine, so I assume that the error is related to something specific to my code. Below is the code in question:
object GUI {
def test:Integer = 1
}
class GUI extends JFrame{
import GUI._
val ICON_LOCATION:File = new File("Images/iMovies.ico");
val ICON:BufferedImage = Ootil.createImage("iMovies.png");
val TITLE:String = "iVideos";
val LICENSE_NAME:String = "OpenBSD";
def GUI(){
setLayout(new BorderLayout());
createGUI();
pack();
setSize(100,100);
setLocationRelativeTo(null);
setVisible(true);
}
def versionMajor: Integer = 1
def versionMinor: Integer = 0
def versionRevision: Integer = 0
def versionPreReleaseID: String = "alpha"
def versionBuildNumber: String = "1b"
private def createGUI():Unit = {
val panel = new JPanel();
panel.setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
}
def getIcon():BufferedImage = ICON
def getProgramTitle():String = TITLE
def getConfigOptions():LookAndFeelConfigurationOptions = GUIConfigOptions.CONFIG_OPTIONS;
}
To add to Kipton's answer, there's nothing wrong with doing:
class GUI{
def GUI() {
println("something")
}
}
But the result won't be a constructor -- it will be an ordinary method.
val a = new GUI() won't print anything, but calling a.GUI() will.
This is why you didn't get an error message about defining your constructor incorrectly.
When you run the command import GUI._, Scala needs GUI to always evaluate to the same object. This is only the case when GUI is an object, a package, or a val.
In your code, import GUI._ referred to the method GUI that you defined, because the GUI method is defined in a closer scope than object GUI (the fact that the compiler hasn't encountered the definition of def GUI yet doesn't make a difference).
Since import GUI._ referred to the method GUI, which is not a val, object, or package, you got the error message about GUI not being a stable identifier.
Welcome to the Scala community.
Scala constructors work differently than they do in Java. To fix the error, you should put the body of your previously defined GUI() method directly into the class definition, like so,
class GUI extends JFrame{
import GUI._
val ICON_LOCATION:File = new File("Images/iMovies.ico");
val ICON:BufferedImage = Ootil.createImage("iMovies.png");
val TITLE:String = "iVideos";
val LICENSE_NAME:String = "OpenBSD";
// ** stuff that used to be in method GUI() goes below **
setLayout(new BorderLayout());
createGUI();
pack();
setSize(100,100);
setLocationRelativeTo(null);
setVisible(true);
...
}
It takes a little getting used to, but I think you'll find that Scala's way is a lot nicer.
If you want to define an auxiliary constructor, declare a method def this(...) { ... } whose first expression is a call to the primary constructor (in this case just this(), since it doesn't take parameters).
If you want to add parameters to your primary constructor, you would define the class as
class GUI( << some parameters >> ) extends JFrame { ... }
and then you can use the parameters anywhere in this class body.