Howto render a form with list mapping
Asked Answered
C

2

6

I have a Form with a nested list of mappings, but have problems iterating this in the template. The Form looks like this

val assignmentForm : Form[AssignmentData] = Form(
   "acceptedSign" -> nonEmptyText(),
    mapping("activities" -> list (    
      mapping("activityId" -> optional(text), 
          "activityStatus" -> optional(text)) 
          (ActivityData.apply)(ActivityData.unapply))
    )(AssignmentData.apply)(AssignmentData.unapply)
)

I am passing this form into the template and try to iterate over the activities. So far only compiler errors or a complete metadata dump of the Form as a result.

This gives a metadata+data dump of the complete form, with the activity included. (the LI tag is a tab navigator that will contain input fields)

@repeat(assignmentForm("activities")) { activity =>
                    <li>@activity("activityId")</li>
                    }

Iteration sort of works (is the code runs), but it is completely unusable from a user standpoint.

I have also tried various for-loops, only giving me compiler errors, saying

value map is not a member of play.api.data.Field

My questions are:

  1. Is it supposed to be possible to construct such a form, and how is it done?
  2. What other options do I have for rendering input forms with one-to-many relationsships?
Customer answered 14/10, 2012 at 19:46 Comment(5)
I posted this question yesterday: "https://mcmap.net/q/1918440/-zip-style-repeat-over-nested-form/185840" and came up with a tuple-based solution where you can @repeat through nested forms in formA.zip(formB) fashion -- might help...but not sure what problem you're confronting here is, sounds like the form is being produced. You do know that you need to do something like @inputText(activity("activityStatus"), '_label-> "Activity Status") to produce a formfield, right?Freemon
Your solution seems to go down the path where I'm heading, and I'll try it out :). Regarding input fields in my question: Since the iteration that should generate navigation tabs (li elements) failed I left inputs out for brevity.Customer
I discovered that rendering input-fields works perfectly. It is only generating li elements that is problematic. How can the value of a form field be used for such purposes?Customer
create a custom helper called "li.scala.html" in a "views.utils" directory and "@import views.html.li" into templates where you plan to use it. For the contents of the file, follow a field helper example from Play sources "github.com/playframework/Play20/blob/master/framework/src/play/…"Freemon
and then @li("foo.bar") to access nested form content and generate list elementsFreemon
C
1

The solution is as simple as this, navtab.scala.html

@**
* Generate an LI element
*@

@(field: play.api.data.Field)
<li><a href='#@field.id' data-toggle="modal">@field("activityStatus").value</a></li>

Then repeat for the mapped collection in your template

<ul  id="activities">
    @repeat(assignmentForm("activities"), min=0) { activity =>
        @navtab(activity)
    }
</ul>
Customer answered 20/10, 2012 at 5:1 Comment(0)
M
0

You can use indexes method to render list(seq, array) values.

@assignmentForm("activities").indexes.map(i =>
  assignmentForm("activities").indexes(s"[$i]").value
)

But this is unuseful, so I created implicit method

import play.api.data.Field

object FieldExtend {
  implicit class FieldExtend(field: Field) {
    def values: Seq[Option[String]] = {
      field.indexes.map(i => field(s"[$i]").value)
    }
    def containsValue(value: Byte): Boolean = {
      values.contains(Some(value.toString))
    }
  }
}

After import this class, you can use @assignmentForm("activities").values

Mikiso answered 11/1, 2017 at 3:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.