user1197252
user1197252

Reputation:

Method parameter passing from view to controller play-framework

I have this method in my application controller:

public static Result searchJourney(String address) {
    return ok(
        views.html.searchResults.render(Journey.searchByAddress(address),journeyForm)
        );
}

Which takes a string as an argument and passes this string to a model method searchByAddress. The search by address method returns a list of my model objects that are the result of a query. This is then used to populate a form.

public static List<Journey> searchByAddress(String address) {
    return find.where().ilike("start_loc", "%"+address+"%").findList();
}

The problem I am having is getting the address argument from a view form. This is what the view looks like:

@main("Journey Search", "search") {
<body>  
        <form>     
        Search for journeys starting in a town/city:
        <input type="text" name="arg"></br>
        <input type="submit" onsubmit="@routes.Application.searchJourney("@arg")" value="Search">
        </form>
    }

All routing is working as expected but I can't seem to get to pass this argument to the controller method. When I enter a value in the textbox the URL updates to display my input:

http://localhost:9000/search?arg=testvalue

But the results page never gets rendered as I would expect.

Update:

<form action="@routes.Application.searchJourney(arg)">     

    Search for journeys starting in a town/city:
    <input type="text" name="arg"></br>
    <input type="submit" value="Search">
    </form>

Without the quotation and @ symbol around the arg I am getting not found: value arg errors.

The results HTML to be rendered

@(listJourneys: List[Journey], journeyForm: Form[Journey])

  @import helper._

  @main("Search Results", "search") {
      <h1>Search Results</h1>
      <table class="table table-hover">
        <thead>
            <tr>
            <th>#</th>
            <th>Starting Location</th>
            <th>End Location</th>
            <th>Participant Type</th>
            <th>Date</th>
            <th>Time</th>
            <!--<th>User</th>-->
             </thead>
              <tbody>
            </tr>

          @for(journey <- listJourneys) {
                <tr>
                  <td>@journey.id</td>
                  <td>@journey.start_loc</td>
                  <td>@journey.end_loc</td>
                  <td>@journey.participant_type</td>
                  <td>@journey.date</td>
                  <td>@journey.time</td>
                </tr>
          }
              </tbody>
      </table> 
    }

Upvotes: 2

Views: 9290

Answers (1)

biesior
biesior

Reputation: 55798

Use:

@routes.Application.searchJourney(arg)

instead of

@routes.Application.searchJourney("@arg")

BTW, why are you setting it in onsubmit atribute? isn't it better to use common form's action for this purpose?

Edit

Ach, now I understand in general you can not build reverse routes with undeclared arguments, or arguments coming from the user's input in HTML form. They must exist in the moment of the view rendering and must have some value.

For getting what you showed ( http://domain.tld/search?arg=val ) where val becomes from user's input you need to use a route with arg as optional param with some default value (in your case most probably empty string will be good:

GET  /search      controllers.Application.searchJourney(arg: String ?= "") 

action:

public static Result searchJourney(String arg) {
    return ok(
        searchResults.render(Journey.searchByAddress(arg),journeyForm);
    );
}

and then you need set an action of the form to this route without arg and also set its method to get:

<form action="@routes.Application.searchJourney()" method="get">
   ...
</form>

You can also do not set any params in the route:

GET   /search      controllers.Application.searchJourney
or
POST  /search      controllers.Application.searchJourney

And then use for an example DynamicForm to bind fields from request:

public static Result searchJourney() {
    String arg = form().bindFromRequest.get("arg");
    // perform some basic validation here
    return ok(
        searchResults.render(Journey.searchByAddress(arg),journeyForm);
    );
}

Upvotes: 5

Related Questions