Lift redirect to a new page after form submission with parameters - lift

How can I pass results of a form submission to a page that I redirect to?
For example, lets say i have the following logic:
Search Page -> validate
if errors - show Search Page again with errors <--- this part works
else - redirect to New Page(passing search params) <-- no params passed
My form processing looks something like this:
def process() = {
if (nameame== "Joe") {
S.error("Joe not allowed!")
}
val dateRegex="(\\d\\d/\\d\\d/\\d\\d\\d\\d|\\w*)";
if (!birthdate.matches(dateRegex)) {
S.error("birthdate", "Invalid date. Please enter date in the form dd/mm/yyyy.")
}
S.errors match {
case Nil =>S.notice("Name: " + name); S.redirectTo("search-results")
case _ =>S.redirectTo(S.uri)
}
}
As you can see - my search results is not getting a "name" or "birthdate" params. How can I pass the parameters from the form when I do a S.redirectTo call?
Let me know if I can clarify the question somehow.

You can store the parameters in SessionVar's and access them from your search_results snippet or wherever you need them. See http://stable.simply.liftweb.net/#toc-Section-4.4.
Otherwise you could always do:
S.redirectTo("search-results?param1=value1") //Not very clean though

Related

Gatling Conditional on Response Body

I am currently using Gatling and I have a scenario whereby I perform a number of GET requests and depending on the body of the responses I would like to perform a different scenario.
I have this at the moment that doesn't appear to work as expected -
val repeatSpin = scenario("repeatScenario1").repeat(10) {
exec(
scenario1
)
.doIf(bodyString => bodyString.equals("<SwitchEvent/>")){
exec(scenario2)
}
}
What am I doing wrong?
It looks like you've got the .doIf parameters wrong - it either takes a key in the session and the value you expect, like:
.doIf("${bodyString}", "<SwitchEvent/>") { myChain }
Or, an Expression[Boolean] - the argument you get is the session; to get values out of a session you do something like session("bodyString").as[String]. So, passing a function to the doIf could look like
.doIf(session => session("bodyString").as[String].equals("<SwitchEvent/>")) { myChain }

Play Framework 2.4 how to use return statement in Action controller

is there a way to return a value inside Action controller.
I have a method in my User model which returns the number of friends of a given user.
def nrOfFriends(current_user: Long): Int = {
DB.withConnection{ implicit connection =>
var nr: Int = SQL("select count(*) from friend where user_id_1=" + current_user + " or user_id_2=" + current_user).as(scalar[Int].single)
nr
}
}
In my controller, I just want to return the value from the model
def freunde() = IsAuthenticated { username => _ =>
User.findByUsername(username).map { user =>
var nr: Int = Friend.nrOfFriends(user.id.get)
Ok(""+nr)
}.getOrElse(Forbidden)
}
But in the way that is written, it will print "empty string " concatenated with the number
If I replace Ok(""+nr) with Ok(nr) I receive the following error:
"Cannot write an instance of Int to HTTP response. Try to define a Writeable[Int]"
I need for my action to return a value so that I can pass the value from the action to header.views.html inside the navbar something like that
#Freund.freunde Friends
if you want your response to just be the value of nr you can simply call nr.toString:
def freunde() = IsAuthenticated { username => _ =>
User.findByUsername(username).map { user =>
var nr: Int = Friend.nrOfFriends(user.id.get)
Ok(nr.toString)
}.getOrElse(Forbidden)
}
The error you're getting makes reference to the fact that Int doesn't have an implicit Writeable[Int] in scope. So play doesn't know how display an Int in an http response.
You can add make Int writeable by putting this in scope:
implicit val intWriteable = play.api.http.Writeable[Int](_.toString.getBytes, None)
Then you would be able to just say:
Ok(nr)
without error.
However, it sounds like you just want the result of nrOfFriends inside an unrelated template. If that's the case, you should be using an Action at all. Instead just call your model function inside the template where you need the data.
#User.nrOfFriends(user.id) Friends
Of course you would need to pass in the user to the template as well.
You didn't post a full sample of all the code involved in what you are trying to accomplish so I think this is the best I can do for now. Perhaps try posting the base template that your <a> is in.
An important point is that Actions are for production an HTTP response, and not just plain data internally to the application.
An action of a controller handles a request and generates a result to be sent to the client. In other words, an action returns a play.api.mvc.Result value, representing the HTTP response to send to the web client. In your example Ok constructs a 200 OK response. The body of the response must be one of the predefined types, including text/plain, json, and html. The number of a friends is an integer and is NOT an acceptable type of the body. Therefore, a simple way to address this problem is to convert it into a text/plain using .toString().
On the other hand, you can define a writer for Int that lets Play know how to convert an integer into a json format.
For more details, please take a look at this https://www.playframework.com/documentation/2.2.x/ScalaActions.

How can I parse out get request parameters in spray-routing?

This is what the section of code looks like
get{
respondWithMediaType(MediaTypes.`application/json`){
entity(as[HttpRequest]){
obj => complete{
println(obj)
"ok"
}
}
}
}~
I can map the request to a spray.http.HttpRequest object and I can extract the uri from this object but I imagine there is an easier way to parse out the parameters in a get request than doing it manually.
For example if my get request is
http://localhost:8080/url?id=23434&age=24
I want to be able to get id and age out of this request
Actually you can do this much much better. In routing there are two directives: parameter and parameters, I guess the difference is clear, you can also use some modifiers: ! and ?. In case of !, it means that this parameter must be provided or the request is going to be rejected and ? returns an option, so you can provide a default parameter in this case. Example:
val route: Route = {
(path("search") & get) {
parameter("q"!) { query =>
....
}
}
}
val route: Route = {
(path("search") & get) {
parameters("q"!, "filter" ? "all") { (query, filter) =>
...
}
}
}

How do I clear one set of errors on a two form page in zend

I have a one page website that has two seperate forms that need to be posted back to the same page, the problem being, that if I submit one form, the error checking is done on both, so displays error messages for both. What I need is that if form one is submit, only form ones' error messages appear, and not form twos. Is this possible in zend?
It isn't a problem for zend to do - but it is a problem for you to solve!
If you give your form a hidden field, or if you have a field ID unique to one form, you should be able to check which form has been submitted in your controller, then you tell zend which form you want it to check. Something like the following should do the job, it will check for a field with the ID unique_form_one_field which obviously should only be on form one, this could be a hidden field for example:
// Get the forms:
$form1 = $this->_helper->formLoader('form_one');
$form2 = $this->_helper->formLoader('form_two');
// Check if there is a POST:
if (!$request->isPost())
{
// It isn't show the forms:
$this->view->form_one = $form1;
$this->view->form_two = $form2;
}
else
{
// It is, get the POST data:
$post_data = $request->getPost();
// Check if form one has been submitted:
if (isset($post_data['unique_form_one_field']))
{
// Check if form one is valid:
if (!$form1->isValid($post_data))
{
// Its got an error, display the forms again, form one will now be populated with the data and also the error messages:
$this->view->form_one = $form1;
$this->view->form_two = $form2;
}
else
{
// Form one was valid - do what you want to process it:
}
}
else
{
// Check if form two is valid:
if (!$form2->isValid($post_data))
{
// Its got an error, display the forms again, form two will now be populated with the data and also the error messages:
$this->view->form_one = $form1;
$this->view->form_two = $form2;
}
else
{
// Form two was valid - do what you want to process it:
}
}
}

Change in URL to trigger Event in GWT

I am iterating through some data and generating parameterized URL links based on some conditions like this:
finishedHTML.append("<a href=\"http://" + domain + "&service=" + allEvents[eventCounter].EventService +"&day="+ offSet+(-1 * i) +"\"><img src=\"/info.jpg\" alt=\"Info\"/>");
I had the beginning of my application checking for URL parameters when the page was loaded/refreshed, and take some action depending on if the parameters were there and what they were.
However, I added a # to the beginning of the paramters, so the page wouldn't need to be refreshed, but now it's not triggering the function that checks the URL.
My question is how can I trigger an event in GWT when a user clicks a link? Do I need to generate GWT controls, and link a click handler? Is it possible to setup an event that fires when the URL is changed???
UPDATE:
Adam answered part of the initial question, but I can't get the querystring after "#". Is there a better way than the function below:
public static String getQueryString()
{
return Window.Location.getQueryString();
}
In other words, if I enter example.com?service=1 I get service=1 as my querystring. If I enter example.com#?service=1, I get a null value for the querystring..
Use History.addValueChangeHandler( handler ), and create a handler to catch the URL changes.
There's no need for click handlers etc., any change of the "hash" part in the URL will be sufficient.
EDIT:
See this code example - it will parse URLs of the form http://mydomain/my/path#tok1&tok2&tok3
public void onValueChange(ValueChangeEvent<String> event) {
String hash = event.getValue();
if ( hash.length() == 0 ) {
return;
}
String[] historyTokens = hash.split("&",0);
// do stuff according to tokens
}
(Just responding to your Update)
Have you tried
History.getToken()
to get the value after the "#"?