play framework chain multiple scala functions - scala

I am writing my first application in Java. In one of my views, I have a couple of helper functions:
#**********************************
* Helper generating table columns *
***********************************#
#tableColumn(content:String) = {
<td>
#content
</td>
}
and
#**********************************
* Helper to convert boolean to string *
***********************************#
#convertBooleanToString(flag:Boolean) {
if (flag) {
"Yes"
} else {
"No"
}
}
I am trying to use these 2 functions as below but getting compiler error.
<tr>
<td>Completed</td>
#for(item <- items) {
#tableColumn(convertBooleanToString(item.isComplete))
}
</tr>
the error that i get is as below:
illegal start of simple expression
Can you please help?

While reproducing I don't get your error message. Please give more code.
But for now you can try:
#**********************************
* Helper generating table columns *
***********************************#
#tableColumn(content:String) = {
<td>
#content
</td>
}
#**********************************
* Helper to convert boolean to string *
***********************************#
#convertBooleanToString(flag:Boolean) = #{if (flag) "Yes" else "No"}
<tr>
<td>Completed</td>
#for(item <- items) {
#tableColumn(convertBooleanToString(item.isComplete))
}
</tr>

Related

trying to check if condition inside a for loop in scala getting compilation error in scala. illegal start of simple expression

my code looks like below.
<Tr>
#for (r <- addressChangeList) {
#for (rl <- requestList) {
#if (#r.getRequest_reqnbr() == #rl.getRequestNumber()) { <td>#rl.getRequestNumber() </td> } else {
<td> No request found</td>}
}
}
</tr>
giving me compilation error:
illegal start of simple expression
I am new to Scala so please help me also how to break the loop if condition matched.
I think your problem is the use of #: you only use # at the start of an expression or block. From your code, this line:
#if (#r.getRequest_reqnbr() == #rl.getRequestNumber()) { <td>#rl.getRequestNumber() </td> } else {
should be
#if (r.getRequest_reqnbr() == rl.getRequestNumber()) { <td>rl.getRequestNumber() </td> } else {

Mapping OneToMany in Scala Play framework not inserting data to the second table

Question is - how should I take data from this kind of inputs and pass it properly to DB (by SORM framework)?
I try to pass data to two tables in my DB, the result of my work is that while the values are properly inserted to the first table (Author), second one (Book) remains untouched.
Probably my problem is that I am not propely naming nested, repeated inputs on my page, but i cant find proper way to do this (I'm fairly new to Scala, so I probably lack of experience on this).
Ok(Json.toJson(author))
in addData in Application.scala shows me
{"name":"what","books":[]}
so I think, that the problem is in binding data from request.
I tried to follow examples here: How to model an entity with many children in Sorm? and here: https://www.playframework.com/documentation/2.1.1/ScalaForms, by operating on the template "play-scala" from Play framework, so i've got code like this:
Models are:
case class Author(name: String, books: Seq[Book]) {
}
object Author {
implicit val authorFormat = Json.format[Author]
}
case class Book(title: String ) {
}
object Book {
implicit val bookFormat = Json.format[Book]
}
case class AuthorBook(name: Author, title: Book) {
}
The scala.index.html
<table>
<tr>
<td>
On the left Author, on the right Book
<td>
</tr>
<tr>
<td>
<ul id="authors"></ul>
</td>
<td>
<ul id="books"></ul>
</td>
</tr>
</table>
<table>
<form action="#routes.Application.addData()" method ="post">
<tr>
<td>Author: <input name="author" type="text">
</td>
<td>Books: <input name="books.title[0]" type="text"><br><input name="books.title[1]" type="text">
</td>
</tr>
<tr>
<td>
<button>Submit</button>
</td>
</tr>
</form>
</table>
And Application.scala
class Application extends Controller {
def index = Action {
Ok(views.html.index("E-Library"))
}
val authorForm: Form[Author] = Form {
mapping(
"author" -> text,
"books" -> seq(
mapping(
"title" -> text)(Book.apply)(Book.unapply)
)
)(Author.apply)(Author.unapply)
}
def error = Action {
Ok("error")
}
def addData = Action { implicit request =>
authorForm.bindFromRequest.fold(
formWithErrors => {
BadRequest("Bad request!")
},
authorF => {
val author = DB.save(authorF)
Ok(Json.toJson(author))
//Redirect(routes.Application.index())
}
)
}
def getAuthor = Action {
val dataAuthor = DB.query[Author].fetch
Ok(Json.toJson(dataAuthor))
}
def getBook = Action {
val dataBook = DB.query[Book].fetch
Ok(Json.toJson(dataBook))
}
def getData = Action {
Redirect(routes.Application.index())
}
}
Found it!
As mentioned here: Nested form in Play! Scala 2.2
I needed to rename input names in my form from
book.title[0]
to
book[0].title.

Github markdown, syntax highlight of code blocks in the table cell

Markdown has pipe table syntax but it's not enough for some cases.
| table | syntax | without multiline cell content |
So, we can use HTML table tags.
<table>
<tr>
<td>
```csharp
const int x = 3;
const string y = "foo";
readonly Object obj = getObject();
```
</td>
<td>
```nemerle
def x : int = 3;
def y : string = "foo";
def obj : Object = getObject();
```
</td>
<td>
Variables defined with <code>def</code> cannot be changed once defined. This is similar to <code>readonly</code> or <code>const</code> in C# or <code>final</code> in Java. Most variables in Nemerle aren't explicitly typed like this.
</td>
</tr>
But some time ago syntax highlighting was broken and this wiki page looks ugly now. Any ideas on how to fix this?
You can use <pre> in tables, as teh_senaus said. But if you do that, syntax highlighting won't work... or will it?
Through random experimentation I found that GitHub allows specifying it with <pre lang="csharp">. This has the same effect that ```csharp does of setting the syntax highlighting to C#.
This isn't really documented anywhere in GitHub's help center, nor in linguist's documentation. But it works, even inside of tables.
So for your example table, the new code would be as follows:
<table>
<tr>
<td>
<pre lang="csharp">
const int x = 3;
const string y = "foo";
readonly Object obj = getObject();
</pre>
</td>
<td>
<pre lang="nemerle">
def x : int = 3;
def y : string = "foo";
def obj : Object = getObject();
</pre>
</td>
<td>
Variables defined with <code>def</code> cannot be changed once defined. This is similar to <code>readonly</code> or <code>const</code> in C# or <code>final</code> in Java. Most variables in Nemerle aren't explicitly typed like this.
</td>
</tr>
Add a blank line between the <td> and the code block.
Here's the fixed markdown:
<table>
<tr>
<td>
```csharp
const int x = 3;
const string y = "foo";
readonly Object obj = getObject();
```
</td>
<td>
```nemerle
def x : int = 3;
def y : string = "foo";
def obj : Object = getObject();
```
</td>
<td>
Variables defined with <code>def</code> cannot be changed once defined. This is similar to <code>readonly</code> or <code>const</code> in C# or <code>final</code> in Java. Most variables in Nemerle aren't explicitly typed like this.
</td>
</tr>
</table>
and the result:
You can use <pre>. Syntax highlighting won't work, but at least it will be formatted properly.
<td><pre>
const int x = 3;
const string y = "foo";
readonly Object obj = getObject();
</pre></td>
Another way is using multiple ` and <br>, but Syntax highlighting won't work .
|1|2|3
-|-|-
`const int x = 3;`<br>` const string y = "foo";`<br>`readonly Object obj =getObject();`|`def x : int = 3;`<br>`def y : string = "foo";`<br>`def obj : Object = getObject(); `|Variables defined with `def` cannot be changed once defined. This is similar to `readonly` or `const` in C# or `final` in Java. Most variables in Nemerle aren't explicitly typed like this.explicitly typed like this.
The trick is to use the backticks around your code, while wrapping it all with a <pre> tag, like so:
<pre lang=html>`<input readonly>`</pre>
Here's a screenshot of how it renders, from my own use case:
You can also :
A | B | C
-- | -- | --
x | y | Some code : <pre lang=php>function sayHello($someArg)</pre>
1 | 2 | 3

How can I bind snippet function to onclick event from button or image?

I have defined this function to build a list os students, each one with his name, surname and an image, that depending an attribute can be a tick or a cross. I want to assign to the tag academic(my image) the onClick event to call a function in my snippet called academic(Student s) which receives a student,and then redirect to another page. Can anyone help me??
def students(xhtml: NodeSeq) = {
def bindStudents(template: NodeSeq): NodeSeq = {
studentsList.flatMap {
s => bind("studentTag", template, "name" -> s.Name, "surname" -> s.Surname,
AttrBindParam("academic", if (s.HasIssue("Academic")) tickUrl else crossUrl, "src"),
)}
}
bind("list", xhtml, "studentsList" -> bindStudents _)
}
def academic(s:Student)={
//do some stuff with s
redirectTo("/OtherPage.html")
}
HTML CODE
<list:studentsList>
<tr>
<td> <studentTag:name /> </td>
<td> <studentTag:surname /> </td>
<td>
<img studentTag:academic=""/>
</td>
</list:studentsList>
There is a method in SHtml called 'onEvent'.
I'm not very sure how to do this in the old way, but if you are using new designer-friendly CSS binding helpers, it will be very simple:
HTML template:
<div data-lift="MySnippet">
Name:<span id="name">Student Name</span>
SurName:<div class="surname">Surname</span>
<img src="imageURL" class="clickable"/>
</div>
Here is the snippet:
class MySnippet
{
val studentName = "whatever"
val surName = "..."
def onClickCallback(s: String): JsCmd = {
// Do what ever you want, BTW, I never have idea
// what the ``s`` the lift will passed in.
Alert('Hey, you clicked me.') // This is the javascript that browser will execute when user click on the element.
}
// Note there is no argument list
def render = {
"#name" #> studentName & // Replace the HTML tag with id="name" to studentName
".surname" #> surName & // Replace the HTML tag with class=surname to surName
".clickable [onClick]" #> SHtml.onEvent(onClickCallback) // Append onClick attribute to HTML tag that has "clickable" class, and it will calle onClickCallable in your snippet.
}
}
Update
Sorry, I didn't notice that you are binding to a list. But since there is curried function, it would not be too difficult either.
HTML code:
<table data-lift="MySnippet">
<tr>
<td><span class="name">Name</span></td>
<td><span class="surname">SurName</span></td>
<td><img src="test.jpg"/> </td>
</tr>
</talbe>
case class Student(name: String, surname: String)
class MySnippet
{
def onClickCallback(student: Student)(s: String): JsCmd = {
Alert("You Click:" + student)
}
val xs = Student("Brian", "Hsu") :: Student("David", "Walter") :: Nil
def render = {
"tr" #> xs.map { student =>
".name" #> student.name &
".surname" #> student.surname &
".clickable [onClick]" #> SHtml.onEvent(onClickCallback(student)_)
}
}
}

Lift: Refresh/Reload Snippet

i'm using an AjaxSelect which contains several ids. By selecting an id the additional information to this id should be displayed in a given table which will be generated by a snippet. Now i want to know which would be the best solution to refresh my list?
HTML:
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
</tr>
</thead>
<tbody>
<tr class="lift:MainScreen.cars">
<td><car:name /></td>
<td><car:type /></td>
</tr>
</tbody>
</table>
SCALA:
def doSelect(msg: NodeSeq) = {
SHtml.ajaxSelect(cars.map(i => (i.no.toString, i.no.toString + ". Car")),
Empty, {
selectedCar =>
controller.chooseCar(selectedCar.toInt)
// RELOAD TABLE
})
}
def cars(node: NodeSeq): NodeSeq = {
val cars = controller.chosenCarFamily.cars
cars match {
case null => Text("There is no items in db")
case game => game.flatMap(i =>
bind("car", node,
"name" -> car.name,
"type" -> car.type))
}
}
You should use ValueCell and WiringUI. Very good examples can be found at simple_wiring and invoice_wiring.
When using WiringUI, each time the valueCell cell is updated, the content linked with WiringUI.apply(cell) will be updated. So it should do the trick.
Here is an example for your specific case:
HTML:
Same as yours
SCALA:
class MainScreen{
def doSelect(msg: NodeSeq) // same as yours
def cars = WiringUI.apply(controller.chosenCarFamily)(displayResult)
def displayResult(carFamily:CarFamily)(node: NodeSeq) ={
carFamily.cars match {
case null => Text("There is no items in db")
case game => game.flatMap(i =>
bind("car", node,
"name" -> i.name,
"type" -> i.type))
}
}
}
object Controller{
val selectedCar = ValueCell(1)
def chooseCar = sectectedCar.set
val chosenCarFamily = selectedCar.lift(car:Int => //Stuff to output the family)
}