8

I have a model class in the following structure:

public class User {
   public String name;
   public Long id;
}

public class Play {
   public String name;
   public User user;
}

Now i want to have a form based on Play class. So I have an editPlay view which takes Form[Play] as an input. In the view I have a form which calls an update action on submit:

@form (routes.PlayController.update()) 
{..}

but I cannot find the right way to bind the user field in a way I'll receive it properly in the controller:

Form<Play> formPlay = form(Play.class).bindFromRequest();
Play playObj = formPlay.get();

According to the API, Form.Field value is always a string. Is there some other way to automatic bind an input to the User Object?

Thanks

df'
  • 300
  • 4
  • 14
Shaharko
  • 136
  • 1
  • 6

2 Answers2

15

You can make use of custom DataBinder In the play.scla.html:

@form (routes.PlayController.update()) 
{
  <input type="hidden" name="user" id="user" value="@play.user.id"/>
}

in your method in the controller

public static Result update()
{
  // add a formatter which takes you field and convert it to the proper object
  // this will be called automatically when you call bindFromRequest()

  Formatters.register(User.class, new Formatters.SimpleFormatter<User>(){
    @Override
    public User parse(String input, Locale arg1) throws ParseException {
      // here I extract It from the DB
      User user = User.find.byId(new Long(input));
      return user;
    }

    @Override
    public String print(User user, Locale arg1) {
      return user.id.toString();
    }
  });
  Form<Play> formPlay = form(Play.class).bindFromRequest();
  Play playObj = formPlay.get();
}
Ahmed Aswani
  • 8,271
  • 7
  • 33
  • 54
  • 2
    Is it possible to put the register call in the global object or somewhere similar so there is no need for this boilerplate code in every controller? – nylund Dec 25 '12 at 10:41
  • 1
    Note that, you have to call Formatters.register(...) before you call Form.form(...).bindFromRequest() if you want this formatter to work. Just had a headache because of that. – Moebius Jul 17 '14 at 12:30
  • In Play 2.5, the Formatters.register method is now non-static. Please refer to https://www.playframework.com/documentation/2.5.x/JavaForms#Register-a-custom-DataBinder for a documentation how to handle it in that case. – koppor Aug 07 '16 at 00:05
  • How can I do it without `static`? – martin Nov 04 '16 at 23:42
2

I'm not quite sure I understand your question, but basically I have been handling forms like this:

 final static Form<Play> playForm = form(Play.class);
 ...
 public static Result editPlay(){
     Form<Play> newPlayForm = form(User.class).bindFromRequest();
     Play newPlay = newPlayForm.get();
     ....    
 }

I serve and render the template from an action using:

return ok(play_form_template.render(playForm));

Then in the template:

 @(playForm: Form[Play])
 @import helper._

 @helper.form(action = routes.Application.editPlay()) {
      @helper.inputText(playForm("name"))
      ...
 }
wfbarksdale
  • 7,498
  • 15
  • 65
  • 88