Skip to content

Instantly share code, notes, and snippets.

@bblfish
Created December 25, 2013 10:08
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bblfish/8121905 to your computer and use it in GitHub Desktop.
Save bblfish/8121905 to your computer and use it in GitHub Desktop.
A simple ajax call using scala-js
package example
import scala.language.dynamics
import scala.scalajs.js
import js.Dynamic.{ global => g }
import org.scalajs.jquery.{jQuery => jQ, JQueryXHR, JQueryAjaxSettings}
//import scala.scalajs.js.{Dictionary, String, Any}
//code by Benjamin Jackman published to the Scala.js mailing list on Dec 16
class JsObjectBuilder extends scala.Dynamic {
def applyDynamicNamed[A](name: String)(args: (String, js.Any)*): A = {
println(s"applyDynamicNamed($name)(args: $args")
if (name != "apply") {
sys.error("Call jsObj like this jsObj(x=1, y=2) which returns a javascript object that is {x:1,y:2}")
}
val obj = js.Object().asInstanceOf[js.Dictionary]
args.foreach { case (name, value) =>
obj(name) = value
}
obj.asInstanceOf[A]
}
//Allows for jsObj()
def applyDynamic[A](name : String)(args: Nothing*) = {
if (args.nonEmpty) {
sys.error("Call jsObj only with named parameters.")
}
js.Object().asInstanceOf[A]
}
//Note that jsObj can also be given a type parameter
//that type will be used as the return type,
//However it's just a NOP and doesn't do real type
//safety
}
object ScalaJSExample {
val console = js.Dynamic.global.console
def main(): Unit = {
console.log("hello")
val title = jQ("#h1")
title.replaceWith("<h2>New Title<h2>")
val paragraph = g.document.createElement("p")
paragraph.innerHTML = "<strong>It works now!</strong>"
g.document.getElementById("playground").appendChild(paragraph)
val ttl=jQ("#turtle")
val jsObj = new JsObjectBuilder
val json = jsObj(url = "http://www.w3.org/People/Berners-Lee/card",
success = (data: js.Any, textStatus: js.String, jqXHR: JQueryXHR) =>{
console.log(s"data=$data,text=$textStatus,jqXHR=$jqXHR");
js.Dictionary()
},
error = ( jqXHR: JQueryXHR, textStatus: js.String, errorThrow: js.String) => {
console.log(s"jqXHR=$jqXHR,text=$textStatus,err=$errorThrow");
js.Dictionary()
},
`type` = "GET"
)
jQ.ajax(json)
// jQ.ajax(js.Dictionary(
// "url" -> {val str: js.Any = "http://www.w3.org/People/Berners-Lee/card"; str},
// "success" -> { val res: js.Any = test _; res },
// "error" -> { val res: js.Any = err _; res } ,
// "type" -> { val str: js.Any = "GET"; str }
// ).asInstanceOf[JQueryAjaxSettings]
// )
}
private def test(data: js.Any, textStatus: js.String, jqXHR: JQueryXHR): js.Dynamic = {
console.log(s"data=$data,text=$textStatus,jqXHR=$jqXHR");
null
}
private def err(jqXHR: JQueryXHR, textStatus: js.String, errorThrow: js.String) : js.Any = {
console.log(s"jqXHR=$jqXHR,text=$textStatus,err=$errorThrow");
js.Dictionary()
}
}
@bblfish
Copy link
Author

bblfish commented Dec 25, 2013

The code above compiles but it gives me a

  Uncaught TypeError: Object #<Object> has no method 'scala_Nothing' 

It does go into the applyDynamicNamed part and write out to the JS Console

  applyDynamicNamed(apply)(args: WrappedArray((url,http://www.w3.org/People/Berners-Lee/card), (success,function () { [native code] }), (error,function () { [native code] }), (type,GET)) 

The code generated by compiler "2.11.0-M7" which is close to the 2.10 one ( which has the same problem) is:

var json = ScalaJS.as.scala_Nothing(jsObj.applyDynamicNamed__T__Lscala_collection_Seq__O("apply", ScalaJS.modules.scala_Predef().wrapRefArray__AO__Lscala_collection_mutable_WrappedArray(ScalaJS.asArrayOf.java_lang_Object(ScalaJS.makeNativeArrayWrapper(ScalaJS.data.scala_Tuple2.getArrayOf(), [new ScalaJS.c.scala_Tuple2().init___O__O("url", "http://www.w3.org/People/Berners-Lee/card"), new ScalaJS.c.scala_Tuple2().init___O__O("success", (function(data, textStatus, jqXHR) {

    return this.$anonfun$2__Lscala_scalajs_js_Any__Lscala_scalajs_js_String__Lorg_scalajs_jquery_JQueryXHR__Lscala_scalajs_js_Dictionary(data, textStatus, jqXHR)

  })["bind"](this)), new ScalaJS.c.scala_Tuple2().init___O__O("error", (function(jqXHR$2, textStatus$2, errorThrow) {

    return this.$anonfun$3__Lorg_scalajs_jquery_JQueryXHR__Lscala_scalajs_js_String__Lscala_scalajs_js_String__Lscala_scalajs_js_Dictionary(jqXHR$2, textStatus$2, errorThrow)

  })["bind"](this)), new ScalaJS.c.scala_Tuple2().init___O__O("type", "GET")]), 1))));

@bblfish
Copy link
Author

bblfish commented Dec 25, 2013

found the answer: I forgot to type the answer jsObj[org.scalajs.jquery.JQueryAjaxSettings. This compiles
and runs correctly:

    val json = jsObj[org.scalajs.jquery.JQueryAjaxSettings](url = "http://www.w3.org/People/Berners-Lee/card",
            success =   (data: js.Any, textStatus: js.String, jqXHR: JQueryXHR) =>{
              console.log(s"data=$data,text=$textStatus,jqXHR=$jqXHR");
              js.Dictionary()
            },
            error =  ( jqXHR: JQueryXHR, textStatus: js.String, errorThrow: js.String) => {
              console.log(s"jqXHR=$jqXHR,text=$textStatus,err=$errorThrow");
              js.Dictionary()
            },
          `type` = "GET"
    )
    jQ.ajax(json)

Copy link

ghost commented Dec 25, 2013

I'm building a cordova application using scalajs and these examples have been very useful ! Thanks.
But I can't get the scala named parameters to work... The compiler complains "Cannot resolve symbol url, success, error and type"
Any idea of what could be wrong ?

@bblfish
Copy link
Author

bblfish commented Jan 5, 2014

Sebastien gave a new response to this here: https://groups.google.com/d/msg/scala-js/im08n5nxVnI/d31ibVSI_iUJ

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment