Search code examples
javaformsscalaplayframework-2.0bootstrap-form-helper

@Repeat Form Helper with complex object - Play Framework


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

Solution

  • 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))