Play framework if else case Not working - scala

Play framework if else case is not working here
If userprofile.useraccountid, useraccount.id have the same value then not views that id user on view page
my code in the view..
#(userprofiles: List[UserProfile],myFriend:models.MyFriend,userprofile:models.UserProfile,useraccount:models.UserAccount)
#helper.form(action = routes.Application.createMyFriend) {
<br/><br/><br/>
#for(userprofile <- userprofiles){
#if(userprofile.useraccountid != useraccount.id) {
<img src="#routes.Assets.at("images/img2.png")" width="200" height="200" />
<br>
<h5>#userprofile.name</h5>
<h5>#userprofile.useraccountid</h5>=<h5>#useraccount.id</h5>
<h6>#userprofile.gender</h6>
<h6>#userprofile.date_of_birth</h6>
<div class="actions">
<input type="submit" class="btn primary" value="+1 Add As Friend" title="Send Friend Request">
</div>
<br/>
}
}
}
when checking the condition the database values are views in the view page and
#if(userprofile.useraccountid != useraccount.id)
if change the condition to
#if(userprofile.useraccountid == useraccount.id)
Nothing will in the view page.
In this code when run the program the code section
<h5>#userprofile.useraccountid</h5>=<h5>#useraccount.id</h5>
The id's are same here , and that show in the view then the idea is not false.. for example 15=15.
Here the 2 id are same but the checking in the if case is not work properly... or the coding is not right.
Edit
This is in application
def listMyFriend = Action { implicit request =>
var cid=request.session.get("userId")
println("aa",cid)
if (request.session.get("userId") == None) {
Results.Redirect("/")
}
else {
val userprofiles:UserProfile=null
val userprofileId = request.session.get("userId").get.toLong//userProfileId
val userprofile = UserProfile.findUserByAccountId(userprofileId).get
println(userprofile)
/* val myfriendId = request.session.get("myFriendId").get.toLong//myFriendId
val myfriend = MyFriend.friendidByUserIsAccepted(myfriendId,true)
println(myfriend)*/
myFriendForm.bindFromRequest.fold(
errors => BadRequest(views.html.myFriend(errors, userprofile,myfriend,myfrnd)),
myFriend => {
println("errors")
val myFriendOpt = UserProfile.myFriend(userprofile.id.get)
println(myFriendOpt)
myFriendOpt match {
case None =>
}
Results.Redirect("/myFriend")
})
}
}

You have shadowing issues in your code: userprofile is both defined as a parameter of your template and as the variable you get out of the for comprehension.
#(userprofiles: List[UserProfile],myFriend:models.MyFriend,userprofile:models.UserProfile,useraccount:models.UserAccount)
here ---^
#helper.form(action = routes.Application.createMyFriend) {
<br/><br/><br/>
#for(userprofile <- userprofiles){
and here ---^
Try renaming one of the two and sort out which one you want to refer to in your if.

Related

Scala/Twirl variables and scope/defining

I'm a front ender by trade but I've been asked to hop on to a Scala project which leverages the Play framework so includes Twirl. I'm trying to create a template which displays slightly different outputs depending on the string which is passed in.
Here is my code:
#(status: String)(implicit messages: Messages)
#{
if(status == "00") {
val pageTitle = "Page title"
val appStatus = "className"
val title = "message"
val subTitle = "message"
val step1Status = "className"
val step2Status = "className"
val step3Status = "className"
val image1 = "/customs/assets/images/image.png"
val image2 = "/customs/assets/images/image.png"
val image3 = "/customs/assets/images/image.png"
val optionalHeading = ""
val optionalParagraph = ""
val listContents = "<li>#Messages('message')</li><li>#Messages('message')</li>"
val optionalLink = "<br /><a class='button' href='#routes.DashboardController.display(custom)' role='button'>#Messages('message')</a>"
}
if(status == "01") {
//Other variables
}
if(status == "04") {
//Etc...
}
}
#layout(${pageTitle}) {
<div class="content__body">
<div class="hero">
<div class="${appStatus}">
<h1 class="bold-large">#Messages(${title})</h1>
<p>
${afterSubTitle}
</p>
<ol class="appstatus-steps">
<li><span class="${step1Status}"><img alt="Complete" title="Complete" src=" + ${image1} + ">#Messages("messages.Received")</span></li>
<li><span class="${step2Status}"><img alt="Complete" title="Complete" src=" + ${image2} + ">#Messages("messages.Processing")</span></li>
<li><span class="${step3Status}"><img alt="Complete" title="Complete" src=" + ${image3} + ">#Messages("messages.Decision")</span></li>
</ol>
</div>
</div>
${optionalHeading}
${optionalParagraph}
<h2>#Messages("messages.next")</h2>
<ul class="list list-bullet">
${listContents}
</ul>
${optionalLink}
</div>
}
So, as you can see, the idea is that this page is called with a code (status) and based on that string, a number of variables are defined which alter the way the page is formed; content/css classes/images etc.
This doesn't work (you may be surprised to learn!)
It's really unclear to me WHY it doesn't though. I thought that you accessed variables using a ${Variable} format, but it's possible that you're supposed to use the #Variable format instead.
Even when I try to change them to the #Variable way, I'm still getting problems and I loosely understand that this is to do with scope in Scala/Twirl and there's a "defining" keyword which can be used. I've read some documentation but I'm not getting it.
Could anyone shed some light on this?
EDIT
Okay, let's just consider the below code instead:
#(status: String)(implicit messages: Messages)
#{
if(status == "00") {
val myClass = "custom-class-1"
}
if (status == "01") {
val myClass = "custom-class-2"
}
#layout("page title") {
<div class="#myClass">This is a div</div>
}
So 'all I want to do' :) is be able to define a variety of variables based on the status and then use those variables in the template of the page.
Does that make sense? I'm so new to Scala so Tuples/Defining is lost on me at the moment, but I am learning!
You seem to be more used to javascript variables and scopes :)
In Scala and Twirl, if you only define a variable (in this case it's a value because it's immutable) inside an if statement, the value is only accessible inside the if block
One solution could be to have the if statement to return a tuple with all the variables, and use the power of assignment operation, like:
val (myA, myB, myC) = if(something) {
val a = "a"
val b = "b"
val c = "c"
(a,b,c) // this will return the 3 variables/values because if statements are an expression, and expressions return something
} else {
val a = "A"
val b = "B"
val c = "C"
(a,b,c)
}
// now you have a,b,c defined in this scope and you can do whatever you need with them
if you want to return different variables depending on the if statement, you will have more complications. a solution would be to make the not needed variables null or an Option
Let me know if you need anything else better explained :)
EDIT: solution for minified edited example
I don't have anything here to check if it compiles, but it should be something like:
#(status: String)(implicit messages: Messages)
#{
val myClass = if(status == "00") {
"custom-class-1"
} else if (status == "01") {
"custom-class-2"
} else {
""
}
#layout("page title") {
<div class="#myClass">This is a div</div>
}
Alternative using pattern matching:
replace the if/else statement with:
val myClass = status match {
case "00" => "custom-class-1"
case "01" => "custom-class-2"
case _ => ""
}
(the case _ is like "in every other case")
The answer by #pedrorijio is almost exactly correct, but the actual code which worked for me in the end was this:
#myClass = #{status match {
case "00" => "custom-class-1"
case "01" => "custom-class-2"
}}
Thank you for the assistance!

[Play]Don't use multiple parameters in a route for display a view that takes multiple parameters

I'm writing a Play 2.3.2 application in Scala.
In My application I'm using a form representing an Integer range(start, finish).
The range class is written as following:
case class Range (
startDate: Long,
finishDate: Long)
I've defined a form like the following:
val rangeForm: Form[Range] = Form (
mapping(
"startDate" -> longNumber(min = 0, max = System.currentTimeMillis()),
"finishDate" -> longNumber(min = 0, max = System.currentTimeMillis())
)(Range.apply)(Range.unapply)
)
In my StatisticsController class I've defined three four:
calculateStatisticsOnRange(range: Range): Future[(Double, Int)]: that calculate the number and average of click of the user in a range;
getCalculateStatisticsOnRangeForm that display the form
calculateGoodAdvicesHtml that check if the form has errors
displayStatistics(average: Double, count:Int) that display the result of the search.
My form view is implemented like:
#(rangeForm: Form[recommendationsystem.models.Range])
#recommendationsystem.views.html.main("Insert a range")(recommendationsystem.views.html.nav.navbar("statistics")) {
<h1>Insert here the range</h1>
<div class="container">
#helper.form(action = recommendationsystem.controllers.manager.routes.StatisticsController.calculateGoodAdvicesHtml()) {
<label for="startDate">Start Date:</label>
<input type="number" class="form-control" placeholder = "start"
name="startDate" value="#rangeForm("startDate")" />
<input type="number" class="form-control" placeholder="finish"
name="finishDate" value="#rangeForm("finishDate")" />
<button type="submit" class="btn btn-default">Search</button>
}
</div>
}
My controller methods are implemented like:
def getCalculateStatisticsOnRangeForm = Action {
Ok(recommendationsystem.views.html.manager.statistics.forms.rangeform(rangeForm))
}
def calculateGoodAdvicesHtml = Action.async { implicit request =>
val form = rangeForm.bindFromRequest
form.fold(
errors => Future{BadRequest(recommendationsystem.views.html.manager.statistics.forms.rangeform(errors))},
range => {calculateStatisticsOnRange(range) flatMap {result => Future{Redirect(routes.StatisticsController.displayStatistics(result._1, result._2))}}}
)
}
def displayStatistics(average: Double, count:Int) = Action{
Ok(recommendationsystem.views.html.manager.statistics.goodadvise(average, count))
}
In my route file I've the following routes:
GET /statistics/good #recommendationsystem.controllers.manager.StatisticsController.getCalculateStatisticsOnRangeForm
POST /statistics/good #recommendationsystem.controllers.manager.StatisticsController.calculateGoodAdvicesHtml
POST /statistics/good/json #recommendationsystem.controllers.manager.StatisticsController.calculateGoodAdvicesJson
GET /statistics/:average/:count #recommendationsystem.controllers.manager.StatisticsController.displayStatistics(average: Double, count: Int)
I don't like to pass multiple parameters in the route of /statistics/:average/:count, there is an other way to make that?

Playframework 2.2.1 Scala - Form bindFromRequest error

I'm trying to register a tuple to a DB and upload the image to Amazon S3.
I divided the code to two parts : 1) Working Code and 2) Non Working Code.
Working code means It works as expected. The image file is uploaded sucessfully to S3.
Non working code is always folding to index_error page which I'm trying to solve but I can't figure out where I'm missing.
Thank you for help!
Working Code
def index = Action {
Ok(views.html.upload_test_index("File Upload In Play"))
}
def uploadFile = Action(parse.multipartFormData) { request =>
request.body.file("fileUpload").map { video =>
val newFile = File.createTempFile("temp-uploaded-", video.filename)
video.ref.moveTo(newFile, true)
new S3Sender(newFile, video.filename).send
}.getOrElse {
Redirect(routes.Application.index)
}
Ok("File has been uploaded")
}
Non Working Code - Controller
val anuncioForm = Form(
tuple(
"label" -> nonEmptyText,
"imgName" -> text
)
)
def createAnuncio = Action(parse.multipartFormData) { implicit request =>
anuncioForm.bindFromRequest.fold(
formWithErrors => BadRequest(views.html.index_error(formWithErrors)),
{
case (label, imgName) =>
request.body.file("imgName").map { imgName =>
val newFile = File.createTempFile("temp-uploaded-", imgName.filename)
val fileName = imgName.filename
imgName.ref.moveTo(newFile, true)
new S3Sender(newFile, fileName).send
Anuncio.create(label, fileName)
}
println("criou")
Redirect(routes.Application.anuncios)
}
)
}
def anuncios = Action {
Ok(views.html.index(Anuncio.all(), anuncioForm))
}
def newAnuncio = Action {
Ok(views.html.create(anuncioForm))
}
Non Working Code - Template
#(anuncioForm: Form[(String, String)])
#import helper._
#main("Criar um novo anuncio") {
#form(action = routes.Application.createAnuncio, 'enctype -> "multipart/form-data") {
#inputText(anuncioForm("label"))
#*<input type="file" name="imgName">*#
#inputFile(anuncioForm("imgName"))
<input type="submit" value="Create">
}
}
Edited
I used the code below to know the error message.
formWithErrors => BadRequest(views.html.index_error(formWithErrors.errorsAsJson))
Surprisingly I got the message below. I can't figure out why this message?!
{"imgName":["This field is required"]}
Do you need to have the file contents as a part of the form itself? You declare the imgName as a text in the form in your controller, but you use it as a input type="file" in your view, which I would imagine is contradictory.
A few things you could take a look at:
how to handle fileupload into a table in play framework? which talks about separating the file from the form as well as an (untested?) single submit for both a form and a file, and possible some other clues
How to include a picture type in a form in Play!2 in Scala? which is doing something similar to what you are doing
http://www.playframework.com/documentation/2.1.2/ScalaFileUpload

Lift (Scala) form validation

I have a question for which I couldn't find an answer anywhere in the web. I have a lift-based web application written on Scala. There is a form in my application which is driven by a snippet. I use Mapper for my models, and I use override def validations ... to define model's validation parameters. The template code looks like this:
<form class="lift:GroupManager.addGroup?form=POST&action=add">
<div class="row collapse" style="width: 30em">
<div class="small-8 columns">
<span class="group-name prefix radius"></span>
</div>
<div class="small-4 columns">
<span class="submit button small postfix radius">Add New Group</span>
</div>
</div>
</span>
</form>
The snippet code:
def addGroup = {
object groupName extends RequestVar[String]("")
def doAddGroup() = {
val group = Group.create.createdAt(new java.util.Date).groupName(groupName.is)
group.validate match {
case Nil => {
group.save
S.notice("Group '" + group.groupName.is + "' has been added successfully")
}
case errors:List[FieldError] => {
S.error(errors)
}
}
}
".group-name" #> SHtml.text(groupName.is, groupName(_), "id" -> "group-name") &
".submit" #> SHtml.submit("Add group", doAddGroup)
}
The model's validations override:
object groupName extends MappedString(this, 700) {
override def dbColumnName = "group_name"
override def dbNotNull_? = true
override def validations = valMinLen(1, S.?("Group name should not be empty!")) _ ::
valMaxLen(700, S.?("Group name should not be more than 700 characters long!")) _ ::
valUnique(S.?("Group name should be unique!")) _ ::
super.validations
}
Now everything is perfect except the fact that when invalid data is provided, S.error is used to inform user about problems. What I want to do is to highlight the form element (by applying class="error") in which the data is invalid and add a <span> element with the error message in front of the form element. Is there a simple way to do that with Lift framework? Or I should just traverse through errors:List[FieldError] and fetch field information from that array, which does not seem too elegant to me?

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)_)
}
}
}