Forms in Scala play framework - scala

Hello i am a beginner to scala play framework. I am unable to create form with two or more inputs. i googled it and found none in scala programming language. Kindly suggest me an idea regarding how to create multiple inputs in a form using scala. i did this
val form = Form (tuple
(
"firstname"-> text,
"lastname" -> text
)
) and to get the values val(fname,lname) = form.bindFromRequest.get
am i following correct way. Kindly suggest me any idea or resource to learn scala play framework . Thanks in advance

Here is a complete (but simple) form example for Play 2.1.1. Including the view, controller and routes file. I suspect you were missing imports and / or an implicit request. Both of which would be understandable!
The controller (Application.scala):
package controllers
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
object Application extends Controller {
val form = Form(
tuple(
"firstname" -> text,
"lastname" -> text
)
)
def index = Action {
Ok(views.html.index())
}
def submit = Action { implicit request =>
val (fname, lname) = form.bindFromRequest.get
Ok("Hi %s %s".format(fname, lname))
}
}
The view (index.scala.html):
<!DOCTYPE html>
<html>
<head>
<title>Form example</title>
</head>
<body>
<form method="post" autocomplete="on">
First name:<input type="text" name="firstname"><br>
Last name: <input type="text" name="lastname"><br>
<input type="submit">
</form>
</body>
</html>
And the routes:
GET / controllers.Application.index
POST / controllers.Application.submit
NB: The name attributes in your HTML view must match the string literals in your controller form.
Hope that helps.

Play documentation is the best way to learn about forms
https://www.playframework.com/documentation/2.1.1/ScalaForms if you want more then, please have a look at play-example-form project.
http://typesafe.com/activator/template/play-example-form This activator example project on forms explains everything about forms.
1) It explains forms and data binding, validation in the play controller.
2) It explains about Optional parameters in the forms.
3) It explains about complex forms with nested objects for example
case class Student(name: String, age: Int, gender: Optional[Char] = None,
address: Address, other: OtherStuff)
The above case class depends on Address, OtherStuff and
notice that the gender is optional. The example project explains how to deal with such complex object dependencies.
Please download activator from here http://typesafe.com/get-started . then, start the activator in browser UI mode using the command activator ui and type play-example-form in the search to download it. After downloading go to the project root folder and type activator eclipse in case you use eclipse or activator gen-idea in case you Intellij Idea.

Related

ReactJS : How to use "form" tag?

Hello everyone I'm trying to learn ReactJS and I would like to know why everybody is using tag to build forms.
I mean when I use this code:
import { TextInput, Form, View } from 'react-native'
<Form onSubmit={this.onSubmit}>
<TextInput/>
</Form>
I got this error :
Element type is invalid: expected a string (for built-in components)
or a class/function (for composite components) but got: undefined. You
likely forgot to export your component from the file it's defined in.
Or when I use this code :
import { TextInput, form, View } from 'react-native'
render (){
return (
<View>
<form onSubmit={this.onSubmit}>
<TextInput/>
</form>
</View>
);
}
I got this error :
Expected a component class, got [object Object].
I'm trying to fix and use a form but I'm mostly trying to understand how it works :)
Thank you for your time and your responses in advance.
Cheers
React-Native doesn't actually contain a Form tag.
There are libraries such as react-native-form-generator that provide similar functionality to what you are looking for.
Moreover, the error you're getting is trying to tell you exactly that - a class or function which defines a react component is expected where you specify a tag, but it was undefined, since there is no such component.

Why is image-src method-return-type instead of URL/route for Play Framework Module Controller?

I have created a Play Framework module "Ean2BarcodePlayModule" which includes this template "barcode.scala.html" saved in the "views.barcodePackage.tags" package:
#(ean: Long)
<img class="barcode" alt="#ean" src="#controllers.barcodePackage.BarcodeController.getBarcode(ean)" />
After using "activator publish-local", I've then referenced this in the "index.scala.html" template of a test project:
#(message: String)
#main("Welcome to Play") {
#barcodePackage.tags.barcode(5010255079763L)
}
The expected result is
<!-- Redacted for brevity -->
<img class="barcode" alt="5010255079763" src="/barcodeRoutes/5010255079763">
<!-- Redacted for brevity -->
But the actual result is:
<!-- Redacted for brevity -->
<img class="barcode" alt="5010255079763" src="Action(parser=BodyParser(anyContent))">
<!-- Redacted for brevity -->
As will be noted, the controller's action method method's return-type appears where instead the source URL should be, but I don't understand why that is happening or know how to fix it.
The module includes this line in "barcodePackage.routes":
GET /:ean controllers.barcodePackage.BarcodeController.getBarcode(ean:Long)
Meanwhile, the route file in the test project contains:
-> /barcodeRoutes barcodePackage.Routes
This is the code for the module controller:
package controllers.barcodePackage
import models.barcodePackage.Barcode
import play.api.mvc.{Action, Controller}
import play.api.libs.concurrent.Execution.Implicits._
import scala.util.{Failure, Success}
/**
* Created by Brian_Kessler on 3/11/2015.
*/
object BarcodeController extends Controller
{
def getBarcode(ean:Long) = Action.async{
Barcode.renderImage(ean) map {
case Success(imageData) => Ok(imageData).as(Barcode.mimeType)
case Failure(error) => BadRequest("Couldn't generate bar code. Error: " + error.getMessage)
}
}
}
Notes:
Most importantly, I'd like to see the module functionality working as expected.
But I'd also prefer a solution which allows me to successfully specify routes within the module, rather than be required to transcribe them all individually within projects which incorporate the module.
With thanks to Sarvesh Kumar Singh whose response helped put me on the right track, I've figured this out.
So, as I came to understand, the problem was not that the template was not finding the controller, but rather that it was calling the method in the controller instead of the reverse router for the controller.
So, what I really needed to do was tweak the module's template (all the other changes were probably irrelevant) to make sure it called the router instead.
With my present version of play, this meant changing barcode.scala.html to:
#(ean: Long)
<img class="barcode" alt="#ean" src="#controllers.barcodePackage.routes.BarcodeController.getBarcode(ean:Long)" />
Note, the source does NOT start with "#routes", but rather "routes" comes between the package name ("barcodePackage") and the controller name ("BarcodeController").
That is because, your are calling this function by saying #controllers.net.nowhereatall.playforscala.barcodes.barcode(ean), when template is being rendered by play.
Now as you have already specified a route and have bound it to your controllers.net.nowhereatall.playforscala.barcodes.barcode(ean) function.
Change the filename barcode.routes to barcodes.routes
Now, assuming that you have/want to integrated the barcodes.routes file of your sub-project in the main project as follows,
-> /barcodes barcodes.routes
So... now, you will need to change few things.
Move your controllers in barcodes sub-project under the package controllers.barcodes.
You should use Barcodes and not barcodes for object name ( Scala conventions ).
So your controllers.net.nowhereatall.playforscala.barcodes controller should ideally here - controllers.barcodes.Barcodes. But you can place it here -controllers.barcodes.net.nowhereatall.playforscala.Barcodesif you want, just add the part.net.nowhereatall.playforscala` everywhere in the following code.
Now, change the route in your barcodes.routes,
GET /:ean controllers.barcodes.Barcodes.barcode(ean:Long)
Now, you need to do is to specify this route in your twirl template by using the reverse router.
#(ean: Long)
<img class="barcode" alt="#ean" src="#controllers.barcodes.routes.Barcodes.barcode(ean)" />
Now, when the tempate is reandered by play by #barcodes.tags.barcode(5010255079763L), this controllers.barcodes.routes.Barcode(ean) call will be evaluated to /barcodes/5010255079763 by the reverse router ( since you bound the controllers.barcodes.Barcode(ean) to / route ).
hence what you will get in browser is,
<img class="barcode" alt="5010255079763" src="/barcodes/5010255079763" />
You can even get it working by hardcoding the route as given below,
#(ean: Long)
<img class="barcode" alt="#ean" src="/barcodes/#ean" />

Play! Framework Form/HTML Helpers: Separation of Concerns?

I just started playing around with Play 2.1.1 using Scala. Going through some tutorials/sample apps, I came across the helper methods that can be used to create forms, e.g.:
#(myForm: Form[User])
#helper.form(action = routes.Application.submit) {
#helper.inputText(myForm("username"))
#helper.inputPassword(myForm("password"))
}
I am still a n00b to this. But as far as I understand, this basically requires a form object being defined within the controller, which "wraps" the model (simplified):
val loginForm = Form(
tuple(
"email" -> text,
"password" -> text
))
)
def login = Action { implicit request =>
Ok(html.login(loginForm))
}
I found this suprising, as I get the feeling that the indirection through the Form object seems "in the wrong place". What I was expecting was something like this (pseudo):
#(user: User)
#helper.form(action = routes.Application.submit) {
#helper.inputText(() => user.userName)
#helper.inputPassword(() => user.password)
}
...so that one does not have to define the Form object within the controller; all form-related stuff would be located within the view template.
Mixing the "this-will-be-rendered-into-a-form" logic into the controller seems like a minor violation of SOC to me.
Now I'm wondering: Is this just the way things are done in Play, or did I miss something? Is there a "nicer" way to handle this?
Cheers, Alex
I think it would be annoying too with many form definition in controller, especially the apps will involved many form.
But Play!Framework make developer to write code more flexible. You can mix plain HTML inside scala template helper like this :
#helper.form(action = routes.Application.submit) {
<input type="text" name="username">
<input type="password" name="password">
....
}
In my opinion, the scala helper actually helpful with form to update data that have been created before. Because it will bind the existing value into the default input value. And additionally, it also help to display error that caused by object validation.
If the form is not considered the previous value, like login form, I think the use of plain HTML input will be considered better.

Creating a custom field constructor in Play 2 (scala)

I am trying to grok the instructions given in the play 2 scala tutorial for form template helpers. I am getting stuck in the section "Writing your own field constructors". It gives a sample template (without saying what the name of the file should be):
#(elements: helper.FieldElements)
<div class="#if(elements.hasErrors) {error}">
<label for="#elements.id">#elements.label</label>
<div class="input">
#elements.input
<span class="errors">#elements.errors.mkString(", ")</span>
<span class="help">#elements.infos.mkString(", ")</span>
</div>
</div>
Then it shows this code:
object MyHelpers {
implicit val myFields = FieldConstructor(myFieldConstructorTemplate.f)
}
I am confused about how this is supposed to relate to the template. (eg, is the template file supposed to be called myFieldConstructorTemplate.scala.html?) I tried some variations on this without luck.
I'm new to both scala and Play, but I also know play 2 and its docs are new, so I'm not sure what incredibly obvious thing I'm missing.
thanks!
I've just had the same problem, I agree with you the documentation is not clear at all...
Possible error 1
not found: value FieldConstructor
It means that you haven't imported the helper with this instruction :
#import helper._
Possible error 2
not found: value implicitConstructor
It means that you are declaring the field constructor in the wrong place in your template (i.e. : in the #helper.form method). To fix this, I declared my field constructor just after my import instructions :
#import form._
#import helper._
#implicitConstructor = #{ FieldConstructor(foundation_field.render) }
(My foundation_field.scala.html file is in the views.form package).
In the tutorial this code is along the text:
Often you will need to write your own field constructor. Start by
writing a template like:
This means you have to create your own template (xxxx.scala.html) and add that code inside. After that, you import it in your template with the code they provide (remember to add that to each scala template that uses your custom field):
#implicitField = #{ FieldConstructor(xxxx.f) }
Check the samples of Play, the Forms sample uses a similar approach with Twitter bootstrap.
To follow the logic of Scala implicit keyword, the document is implicit too ;)
Scala and Play are too immature right now, for that reason the documentation is very poor.
This SOF answer is very good: https://stackoverflow.com/a/15268122/1163081
You can also check the Play source for more examples: https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/html/
Or this guys appears to discover the solution: https://groups.google.com/forum/#!msg/play-framework/2e1EqZJ-Qks/gXD1oo0IjfcJ

simple database query in lift framework web page

I'm starting out with Lift and been reading a few tutorials and books that are available online. Coming from a JSP (or GWT) background, it's a huge leap, especially since I'm still learning Scala too.
Anyway... I've created the basic site by downloading the lift tar.gz stuff from their site, copied the lift_blank" directory and renamed it to "test". Did the whole "sbt update ~jetty-run" thing etc etc.
What I want to do is modify the "index.html" page to simply have a text field for input, and a button that says "search". Basic idea, you type your firstname, hit "Search", a database query is executed for finding records with a firstname of "what-you-entered-in-the-text-field", and then the results are formatted and displayed on the web page; after the page has refreshed, the text field needs to contain the name that was entered as well.. You type in a different name, hit "search", and new results are displayed on the page. Initially (first time visiting the page), the results are of course empty. Simple stuff...
However, the examples I've all seen use html forms and POST backs etc; I really dislike this, for example users get all flustered when refreshing the page and they get a firefox popup "To display this page, Iceweasel must send information that will repeat any action (such as a search or order confirmation) that was performed earlier."... the page is also refreshed which is something I'd like to avoid.
Previously when I would build this in JSP, I would use all javascript; no "form" tags or anything, just a simple field with javascript events for hitting enter or hitting a "button"... events thaen get channeled to a main javascript function "onQuery" which then creates an AJAX request; when the result comes back from the server, javascript would modify a wrapper "div" element by changing the "innerHTML" value etc. The nice thing here is that the page doesn't refresh, just a tiny subsection of it does, the "table" (actually a div) which holds the results.
How would I re-create a very similar thing in Lift? I'm kind of lost here. I've followed a few examples in the past few days, but again they all use POST / forms. I can handle the scala database querying, and I understand how Lift's templates works, it's just the snippet / comet stuff that I could use a few pointers on.
You can try to use the SHtml.ajaxText function to get the input and to use Wiring on server's side to deal with the request and change automatically the result.
However, with this solution, you no longer need the submit button, but as you don't want a form it should not matter much.
Here is what I think about for the HTML file :
<div id="myHtml" class="lift:surround?with=default;at=content">
<form class="lift:form.ajax">
<input class="lift:SearchForm.name"/>
</form>
Value searched : <span class="lift:SearchForm.display">
</div>
Now on server's side it is a little bit more complicated
class SearchForm{
val name = SHtml.ajaxText("", s=>{ SearchWiring.name.set(s); Noop})
def display = {
WiringUI.apply(SearchWiring.name)(name:String => {"*" #> name} )
}
}
object SearchWiring{
val name = ValueCell("All")
}
I don't know if this is totally rigorous but it is my best thought for your problem. You will find more details about wiring on the official liftweb demo and on Seven Things blog. I hope it will help!
Below is what I ended up using. The one thing I dislike about Lift is all the "magic" that needs to be inserted at various points. I can understand most of this, but the whole " ++ hidden" thing could use some explaining...
The "index.html" page, everything including the "body" tag:
<body class="lift:content_id=main">
<div id="main" class="lift:surround?with=default;at=page">
<lift:Search.search>
Search Query: <query:text/> <query:button/><br/>
<div id="results">
</div>
</lift:Search.search>
</div>
</body>
The "Snippet" code, in a class called "Search.scala" (some of the import statements are unused, a leftover result of attempting different approaches):
package code
package snippet
import scala.xml.{NodeSeq, Text}
import net.liftweb.util._
import net.liftweb.common._
import java.util.Date
import code.lib._
import Helpers._
import common.Main
import common.solr.{Hitlist, Solr}
import net.liftweb.http.{S, StatefulSnippet, SHtml}
import net.liftweb.http.js.JsCmds.SetHtml
import _root_.net.liftweb.http.SHtml._
import _root_.net.liftweb.util.Log
import net.liftweb.http.js.JsCmd
import net.liftweb.http.js.JE.JsRaw
object Search {
def search(xhtml:NodeSeq):NodeSeq = {
var queryText = "(initial)"
def runQuery() = {
println("\n\nQuery: " + queryText)
SetHtml("results", <span>Query: {queryText}</span>)
}//runQuery
ajaxForm(
bind("query", xhtml,
"text" -> text(queryText, queryText = _),
"button" -> submit("Post", runQuery)
) ++ hidden(runQuery _)
)
}//search
}//Search