Play Framework Multiple QueryStrings - scala

I can get one queryString from the template however, never managed to get two.
This is my controller
def get = Action { implicit request =>
val requestedProviderName = request getQueryString "providerName"
val requestedReleaseId = request getQueryString "releaseId"
}
Like that my router produces
Here is my router.conf : http://localhost:9000/fail?providerName=oneProviderName
this is all correct but I want to pass more than one option.
GET /fail #controllers.mycontroller.get
What I have as a view is so basic,
#helper.form(routes.mycontroller.get) {
<select name="providerName" class="selectpicker" data-live-search="true">
#for((providerName, failedReleasesNumber) <- providers){
<option id="selectedvalue" value="#providerName" selected="selected">
#providerName, #failedReleasesNumber
</option>
}
</select>
<div class="row-fluid">
<div class="span6">
<label>Start Date: <input type="date" id="startDate"></label>
<label>End Date: <input type="date" id="endDate"></label>
<label>Release Id: <input type="number" id="releaseId"></label>
<label>Results Start?!: <input type="number" id="resultStart"></label>
<label>Max Results: <input type="number" id="maxResults"></label>
<input type="submit" class="btn btn-primary" value="Get Failed Releases" style="margin-top:-10px">
</div>
</div>
}
My question is more, how I can define these inputs as I want them to be in the QueryPath.
I have searched the web however, couldn't find a solution. Everyone written stuff about router but how to define them in template is unanswered or I am missing something completely. I am using Play Framework 2.1.1 with Scala

For question 1:
To use url like http://localhost:9000/fail?providerName="xyz"&secondQueryString="abc" define like this in routes file
GET /fail controllers.mycontroller.get(providerName: String, secondQueryString: String)
and modify get method signature like get(providerName: String, secondQueryString: String)
For question 2:
When the form action is defined for GET method then by default all the input fields will be passed in query string. Just ensure using same query string names defined for url path (in routes file) and the name used in the html file.

Well I have found my answer, as it is answered before the operation should be GET
However, e.g.
<input type="number" name="maxResults" id="maxResults">
Just id of input field is not enough thus, there should be name field as well and after everything is okay. Even there is no need for input variables to the functions. You can get the variables like
val requestedProviderName = request getQueryString "providerName"
Which returns an optional value of input variable in the template(view).

Related

Spray - Parsing forms with checkboxes

I am setting up a simple API part of which accepts POST requests via form submission. The form requires the user to select one or more checkboxes all sharing the same name e.g.
<form>
<input type='text' name='textval'>
<input type='checkbox' name='cbox' value='val1'> Value 1
<input type='checkbox' name='cbox' value='val2'> Value 2
<button type='submit'>Submit</button>
</form>
I am attempting to handle the request in Spray like so:
path("mypath") {
post {
formFields('textval, 'cbox) { (textval, cbox) =>
// Now what?
}
}
}
I cannot find documentation in the Spray Docs on how to handle such inputs. In fact, this seemed to be an issue that has now been fixed, but I am unsure how to handle this form field with the Spray API
I have found a somewhat hacky solution to meet my needs. I have changed the names of my checkboxes to represent the values associated with them, and I use optional form fields in my spray route
Here is my new form
<form>
<input type='text' name='textval'>
<input type='checkbox' name='cbox1' value='val1'> Value 1
<input type='checkbox' name='cbox2' value='val2'> Value 2
<button type='submit'>Submit</button>
</form>
The route changes accordingly
path("mypath") {
post {
formFields('textval, 'cbox1.?, 'cbox2.?) { (textval, cbox1, cbox2) =>
complete(s"textval:'$textval', cbox1:'$cbox1', cbox2:'$cbox2'")
}
}
}
The optional fields get mapped to type Option[String] which can then be easily checked with .isEmpty or something similar to determine whether the checkbox was checked.
However, one issue is that it will allow forms to be posted with no checkboxes selected since they are all optional. You could perhaps set one as default.

Declare variable to use inside #helper.repeat - PlayFramework

I want to use helper.repeat to create several input elements. But I want to declare the input tags as html instead of using #helper.input methods. But to do that I have to use a #index inside this loop. I am unable to instantiate and increase this variable. I tried something like the code below but I this output appear in html page:
BaseScalaTemplate(play.twirl.api.HtmlFormat$#5a8a0ced) = {0}
is output in html.
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
#index = {0}
#helper.repeat(questionForm("answer.alternatives"), min = 7) { (alternative) =>
<div class="checkbox">
<input type="checkbox" value="#alternative("correct") ">
<input type="text" id="answer_alternatives_(#index)_text" name="answer.alternatives[#index].text" value="">
</div>
}
</div>
</div>
Is there another maybe cleaner way to do what I want? Maybe with #for?
I use playframework 2.4.6 with Java8.
Playframework will let you do what you need, but you will have to do it in another way.
1) Your form definition will have a Seq[String] to save the results that come from the template.
2) Your form definition will need to include this change. In your case:
"answer_alternatives" -> seq(nonEmptyText)
3) Change the name and id from the template to #{alternative.name} so Playframework can link your input text to the sequence of String.
<input type="text" id="#{alternative.name}" name="#{alternative.name}" value="">

Play framework: empty body in post request

Helo! I have a following code:
def foo = Action { request =>
Ok(request.body.asText.getOrElse("no body"))
}
In frontend have a form like this:
<form action="#controllers.routes.Application.foo()" method="POST">
<input name="name" type="text">
<input name="surname" type="text">
<button type="submit">
</form>
If I fill the form and click submit, they gives me result: no body.
But if I add brakepoint in debugger to Ok(..), they shows me, that body is not emty.
AnyContentAsFormUrlEncoded(Map(name -> ArrayBuffer(123), surname -> ArrayBuffer(123)))
Why, that doesn't give me body as text, or as anything else, and how I can get them?
Given your form and your debugging output, you should be using asFormUrlEncoded.
You'll need the following as well:
<form ... enctype="text/plain">
to specify that the payload is plain text. Then the .asText will work.
Your content type probably is something other than text/plain. The BodyParser will only return a result, when the content type is the expected.
edit: Instead of asText try asRaw.

GET form in Scala templates

I'm attempting to create a form using GET to search given some input:
<form class="form-inline" role="form" method="get" action="#routes.Index.search">
<div class="form-group">
<label for="search-field">Search:</label>
<input id="search-field" class="form-control" type="text" name="q" placeholder="Sun"/> </div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
Where the Index controller has the following method:
def search(q: String) = Action.async {
...
}
And my routes file has the following route:
GET /search controllers.Index.search(q: String)
I was expecting that this should work as I expect, which is that a GET request should be made to http://foo.bar/search?q=hello if the value in search-field was hello. Instead I get the following compilation error:
/index.scala.html:8: missing arguments for method search in class ReverseIndex;
follow this method with `_' if you want to treat it as a partially applied function
<form class="form-inline" role="form" method="get" action="#routes.Index.search">
Any help with why this is wrong would be much appreciated.
The problem was that I was not providing default values for the query parameters in the routes file:
GET /search controllers.Index.search(q: String ?= "")
fixed the problem.

Angular JS: sending form field data in a PUT request (like POST does)

I'm trying to write a client that does all four REST verbs (GET/POST/PUT/DELETE) and have gotten all but the PUT done. The REST/CRUD API I'm working from wants to update an entry by calling PUT /realmen/ID-string and including the key-value pairs as JSON. For a POST this seems to work "automatically", but not for a PUT.
My HTML looks like:
<div id="list">
<form novalidate class="edit-form">
<p>Title <input ng-model="realmen.title" type="text" value="{{realmen.title}}" /></p>
<p>Real Men <input ng-model="realmen.realmen" type="text" value="{{realmen.realmen}}" /> </p>
<p>Real Role-Players <input ng-model="realmen.realroleplayers" type="text" value="realmen.realroleplayers}}" /></p>
<p>Loonies <input ng-model="realmen.loonies" type="text" value="{{realmen.loonies}}" /></p>
<p>Munchkins <input ng-model="realmen.munchkins" type="text" value="{{realmen.munchkins}}" /></p>
<input ng-model="realmen.entryId" type="hidden" value="{{entryId}}"/>
<button ng-click="change()">UPDATE ({{entryId}})"</button></p>
</form>
</div>
My controller looks like:
$scope.realmen = RealMen.get({entryId: $routeParams.entryId}, function() {
$scope.master = angular.copy($scope.realmen); // For resetting the form
});
$scope.change = function() {
console.log($scope.realmen);
RealMen.update({entryId: $scope.entryId}, function() {
$location.path('/');
});
}
And finally, my services look like:
angular.module('realmenServices', ['ngResource']).
factory('RealMen', function($resource){
var RealMen = $resource(
'http://localhost\\:3000/realmen/:entryId',
{},
{
query: {method:'GET', params:{entryId:''}, isArray:true},
post: {method:'POST'},
update: {method: 'PUT', params:{entryId:'#entryId'}},
remove: {method:'DELETE'}
});
return RealMen;
});
The PUT is getting called with the correct id value in the URL, but the Request Payload only contains the entryId, so the backend API gets no expected keys and values and essentially blanks out the record in the database.
The console.log($scope.realmen) does show the form fields, along with a lot of extra data. I tried calling RealMen.update($scope.realmen, ...) (similarly to calling .save()), but all those extra fields are tacked on as query string parameters to the URL in a spectacularly ugly fashion.
Because your $scope.realmen is a resource instance, instead of using RealMen.update, you can just call $scope.realmen.$update() (note that there is a "$"). The instance action method will take care of sending the data for you.