How to conditionally assign variable value in template of play framework 2.0? - scala

I want to create a variable called style and assign its value
based on the value of the input parameter #filter
I read the play's documentation, but the current solution I can get
it works is something like: which the list template part is duplicated...
#(filter: String = "error")(body: (String) => Html)
#filter match {
case "HOT" => {
<ul class="list">
<li class="icon-hot">this is a list item..</li>
<li class="icon-hot">this is a list item..</li>
</ul>
}
case "NEW" => {
<ul class="list">
<li class="icon-new">this is a list item..</li>
<li class="icon-new">this is a list item..</li>
</ul>
}
}
How do I assign "icon-new" & "icon-hot" to a variable #style and use it latter when writing the list template like this?
<ul class="list">
<li class="#style">this is a list item..</li>
<li class="#style">this is a list item..</li>
</ul>

This seems to work...
in style.scala.html
#(filter: String = "error")(body: (String) => Html)
#filter match {
case "OPEN" => {
#body("icon-plus")
}
case "FOLLOWING" => {
#body("icon-comments")
}
case "HOT" => {
#body("icon-fire")
}
}
And in list template
#(filter: String = "HOT")
#style(filter) { style =>
<ul class="list">
<li class="#style">this is a list item..</li>
<li class="#style">this is a list item..</li>
</ul>
}
but I'm still not very clear how this works...especially the following part:
(body: (String) => Html)
#body("icon-plus")

Related

"Yield" doesn't work in binding.scala

Several days ago I read about binding.scala and I found it so cool therefore I decided to write my own single page app.
The problem is that I'm trying to add "li" items into "ul" element, but it seems like the component Want doesn't see updates.
The code below:
case class Movie(title: Var[String], raring: Var[Int], watched: Var[Boolean])
var movies = Vars.empty[Movie]
#dom def Want = {
println(movies.bind, "!##!##!##!")
<div class="want">
<ul>
{for (movie <- movies.value) yield {
<li>
<div>
<span>
{movie.title.bind}
</span>
<button onclick={event: Event => {
event.preventDefault()
movies.value.remove(movies.value.indexOf(movie))
println(movies.value)
}}></button>
</div>
</li>
}}
</ul>
</div>
When I change movies nothing happens.
UPDATE
After the comment below I updated the code:
def remove(movie:Movie) = {
movies.value.-=(movie)}
#dom def Want = {
println(movies, "!##!##!##!")
<div class="want">
<ul>
{for (movie <- movies.bind) yield {
<li>
<div>
<span>
{movie.title.bind}
</span>
<button onclick={event: Event => {
event.preventDefault()
remove(movie)
}}></button>
</div>
</li>
}}
</ul>
</div>
}
However, the code doesn't work.
Please change for (movie <- movies.value) to for (movie <- movies).
According to the Scaladoc of value method:
Note: This method must not be invoked inside a #dom method body.

Scala parameter value does not compare correctly - checking for empty string value with if statement in view

I have a view using Scala:
#(user: User = null, scripts: Html = Html(""), isLoggedIn: String = "", currentEmail: String=controllers.helpers.AccessMiddleware.getSessionEmail())(content: Html)
The currentEmail string is what I am interested in. It is empty or "" when a user is not logged into the system and contains an email value when logged in.
I can see that the value is empty or "" when opening the URL/application, but the if statement inside the view continually goes to the else part of the statement, display an empty string and not "Login":
<nav class="navmenu center">
<ul>
<li class="scroll_btn">Home</li>
<li class="scroll_btn">Register</li>
<li class="scroll_btn">Admin</li>
#if(currentEmail == "") {
<li class="scroll_btn">Login</li>
} else {
<li class="scroll_btn">#currentEmail</li>
<li class="scroll_btn">Logout</li>
}
</ul>
</nav>
It always determines that there is a value even though it is empty. Here is the page source:
<nav class="navmenu center">
<ul>
<li class="scroll_btn">Home</li>
<li class="scroll_btn">Register</li>
<li class="scroll_btn">Admin</li>
<li class="scroll_btn"></li>
<li class="scroll_btn">Logout</li>
</ul>
Is there another way to compare to an empty string? Also, how do you make the currentEmail value lower case? .toLowerCase() does not work...
I appreciate the help!
Use Option
Option with forall will handle the case where currentEmail is null
Option(currentEmail).forall(_.isEmpty)
Your code becomes
#if(Option(currentEmail).forall(_.isEmpty)) {
<li class="scroll_btn">Login</li>
} else {
<li class="scroll_btn">#currentEmail</li>
<li class="scroll_btn">Logout</li>
}

Play framework in Scala, scope of #

Scala and play novice here, what's the scope of #?
<ul>
#list.map( x => {
<li> {x.name} </li>
})
</ul>
Gives me the list of names,
<ul>
#list.map( x => {
<li> x.name </li>
})
</ul>
Gives me the "x.name" string repeated in a list.
<ul>
#list.map( x => {
<li> #x.name </li>
})
</ul>
Gives me #x.name string repeated in a list.
So it tells me that x.name isn't considered an expression, but when I use # to make it a Scala expression, the # is dumped as is, and the expression doesn't compute.
Could someone please point me to docs on the scope of #?
Thanks.
From the documentation:
the end of the dynamic statement will be inferred from your code
An example:
Hello #customer.name!
^^^^^^^^^^^^^
Dynamic code
So everything between ul tags in your samples is parsed as scala code.

Unable to locate element error

I am getting an error when trying to click a "Sponsors" link on the page:
unable to locate element, using {:href=>"/Sponsors", :target=>"", :tag_name=>"a"}
Here is the line I am using:
browser.div(:class => "pageContainer").header(:class => "page-header")
.div(:class => "container").nav.ul(:class => "nav nav-pills")
.li(:class => "", :index => 2).a(:href => "/Sponsors", :target => "").click
(FYI: I've tried using index 0 through 4, and removing the index; all resulted in the same error)
Below is the code:
<div class="pageContainer">
<header class="page-header">
<div class="container">
<nav>
<ul class="nav nav-pills">
<li class>...</li>
<li class>...</li>
<li class="dropdown open">...</li>
<li class>
<a href="/Sponsors" target"">
Sponsors
</a>
</li>
<li class="dropdown">...</li>
</ul>
</nav>
Posting as an answer since OP indicates that it's a solution.
Instead of qualifying the whole path to the element, use a single locator (which should still locate the element and should be less fragile if ancestor elements are changed):
browser.a(:href => "/Sponsors").click
browser.a(:text => "Sponsors").click

How to increment a variable in template without loop -- Play 2.1.1, Java

I would like to generate ID's for an HTML list.
The list is generated dynamically from the database.
I cant use a for loop or the list.zipWithIndex function because my logic contains a few loops for the generation of the list already, in which the counter needs to be incremented too. I also tried it with the defining function, but its not allowed to reasign values like this: #{id = id + 1}
Whats the best way to accomplish the generation of Id's?
Thats part of the template (uniqueId needs to be replaced with an integer):
<div id="tree">
<ul>
<li id="uniqueId">
<a class="dashboard" href="/">Dashboard</a>
</li>
<li id="uniqueId">
<b>Products</b>
<ul id="uniqueId">
#for(cat <- Application.allCategories()) {
<li id="uniqueId">
<a class="name" href="#routes.Categories.getd(cat.id).url">#cat.name</a>
<ul>
#for(prod <- Application.allProducts()) {
<li id="uniqueId">
<a class="name" href="#routes.Product.getById(prod.id).url">#prod.name</a>
</li>
#*more code and the closing tags...*#
Use just ... object's id prefixed to make it unique, example for first listing:
#for(cat <- Application.allCategories()) {
<li id="cat_#cat.id">
for second:
#for(prod <- Application.allProducts()) {
<li id="prod_#prod.id">
or if the same product can be displayed in several categories prefix it with cat.id as well:
#for(cat <- Application.allCategories()) {
<li id="cat_#cat.id">
#for(prod <- Application.allProducts()) {
<li id="prod_#(cat.id)_#(prod.id)">