@Repeat Form Helper with complex object - Play Framework
Asked Answered
G

2

6

I don't manage to have a repeated field with selected value according to the data I have in my model.

Currently I have in my User model :

@Required
public String username;

@ManyToMany
public List<Stay> places;

And my Stay model :

@Required
@ManyToOne
public Place place;

@Required
@Formats.DateTime(pattern="yyyy-MM-dd")
public Date startDate;

@Required
@Formats.DateTime(pattern="yyyy-MM-dd")
public Date endDate;

My Scala view form :

    @(formUser: Form[User])
...
    @repeat(formUser("places"), min = 1) { stayField =>
      <div id="groupLocationField">
        // Don't manage to reach User->Places->Place
        @select(formUser("stayField.places"), options(Place.optionsTitle))
        @inputDate(formUser("stayField.startDate"))
        @inputDate(formUser("stayField.endDate"))
      </div>
    }

stayField is a Form.Field type which contains Field(null,places[1],ArrayBuffer(),None,ArrayBuffer(),Some(Paris Mon Oct 29 00:00:00 CET 2018 Wed Jun 11 00:00:00 CEST 2014 null))

But seems to have convert my Place and Dates into a string. @stayField contains the value of my Stay model toString method.

@stayField.value = Paris Mon Oct 29 00:00:00 CET 2018 Wed Jun 11 00:00:00 CEST 2014
@stayField.value.productArity = 1
Graber answered 13/4, 2014 at 13:1 Comment(0)
G
9

Found the solution :

 @repeat(formUser("places"), min = 1) { stayField =>
      <div id="groupLocationField">
        @select(formUser(stayField.name.toString + ".place"), options(Place.optionsTitle))
        @inputDate(formUser(stayField.name.toString + ".startDate"))
        @inputDate(formUser(stayField.name.toString + ".endDate"))
      </div>
    }

stayField.name will show places[1], places[2], etc...

Note that I had to use Place.optionsTitle instead of my classical Place.options that I use in my other @select field.

    public static Map<String,String> optionsTitle() {
        LinkedHashMap<String,String> options = new LinkedHashMap<String,String>();
        for(Place c: Place.find.orderBy("title desc").findList()) {
            options.put(c.title, c.title);
        }
        return options;
    }   
    public static Map<String,String> options() {
        LinkedHashMap<String,String> options = new LinkedHashMap<String,String>();
        for(Place c: Place.find.orderBy("title desc").findList()) {
            options.put(c.id.toString(), c.title);
        }
        return options;
    }

EDIT: In fact I don't have to use specific method optionsTitle(), I forgot to specify the place ID in my select :

@select(formUser(stayField.name.toString + ".place"), options(Place.optionsTitle))

Should become :

@select(formUser(stayField.name.toString + ".place.id"), options(Place.options))
Graber answered 19/4, 2014 at 16:43 Comment(1)
@LVarayut Yes, it does. This is the main reason people try implementing this! :)Heda
I
1

The "selected" value in the template form field should come from the pre-populated form, the helper uses this value to determine which option to mark as selected.

For example, here's an edit form for a User entity from one of my projects:

Controller:

def edit(id: Long) = authorizedAction(Administrator) {
  Ok(views.html.user.edit(id, editUserForm.fill(User.findById(id).get)))
}

Template:

@(id: Long, userForm: Form[User])

@main("Edit User") {
  <h2>Edit User</h2>
  @helper.form(action = routes.UserController.update(id)) {
    <fieldset>
      <input type="hidden" name="id" value="@userForm("id").value" />
      @helper.inputText(userForm("name"), '_label -> "Name")
      @helper.inputText(userForm("email"), '_label -> "Email Address")
      @helper.select(userForm("permission"), 
          models.Permission.displayValues, 
          '_label -> "Permissions", '_default -> "-- Select --",
          '_showConstraints -> false)
    </fieldset>
    // Submit button
  }
}

Now, the select for "permission" will look at the "userForm" property "permission" to determine which HTML option to mark as "selected".

Intermediacy answered 15/4, 2014 at 4:53 Comment(1)
Thanks for your answer. I updated my question to give your more specific information. I try to fill the field from a List<Object>.Graber

© 2022 - 2024 — McMap. All rights reserved.