Get an UndefinedBehaviorError when using a parameter of type case class in an scalajs method which I handover from a play framework Scala/Twirl template view/notify.scala.html:
@(note: Notification, ...)(implicit ...)
<!DOCTYPE html>
<html>
<body>
...
<script type="text/javascript" charset="utf-8">
CommandsJS.notify('@note');
</script>
</body>
</html>
Here the case classes:
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
and the method defined in ScalaJs:
@JSExport
def notify(notification: Notification): Unit = {
...
notification match {
case Email(email, title, _ ) => log.info(s"Email: $email")
case SMS(number, message) => log.info(s"SMS: $number")
}
}
The case class gets instantiated in the controller:
class AppCtrl ... {
def sendNote = silhouette.UserAwareAction { implicit request =>
Ok(views.html.notify(SMS("John","hi John"), ...))
}
}
Get runtime error within javascript console: An undefined behavior was detected: SMS(John,hi John) is not an instance of Notification. Any help/workaround appreciated - thanks
The short answer is: you can't do that.
You're rendering this Play template on the server, passing in the Notification. You can't just embed the Notification
in the JavaScript code, which is what you're doing here:
CommandsJS.notify('@note');
and expect it to work. That isn't a Notification
-- it's a JavaScript String
(containing the value of note.toString
, which is getting automatically called by the way you're using it in the template), which is why you're getting the error that you are seeing.
To make this work, you'd have to serialize the Notification
(as JSON or something) before you pass it into the template, embed that as the String value, and then deserialize it inside notify()
on the client side. I do that occasionally, and it's a bit of a hassle, but there's nothing for it -- you can't just pass strongly-typed Scala objects from the server to the client through the template like this...