I am developing an application with play framework v 2.1
for the views I have to use Scala
I was trying to read through one of the sample code of play framework which can be found here
http://www.playframework.com/documentation/2.0.x/Samples the Forms one
In the views folder of the app there is file views.contact package called form.scala.html
@(contactForm: Form[Contact])
@import helper._
@import helper.twitterBootstrap._
@title = {
Add a new contact <small><a href="@routes.Contacts.edit">Or edit an existing contact</a></small>
}
@phoneField(field: Field, className: String = "phone") = {
@input(field, '_label -> "Phone numbers", '_class -> className) { (id, name, value, _) =>
<input type="text" name="@name" value="@value">
<a class="removePhone btn danger">Remove</a>
}
}
@informationGroup(field: Field, className: String = "profile") = {
<div class="twipsies well @className">
<a class="removeProfile btn danger pull-right">Remove this profile</a>
@inputText(
field("label"),
'_label -> "Label"
)
@inputText(
field("email"),
'_label -> "Email"
)
<div class="phones">
@repeat(field("phones"), min = 0) { phone =>
@phoneField(phone("number"))
}
@**
* Keep an hidden block that will be used as template for Javascript copy code
**@
@phoneField(
field("phones[x].number"),
className = "phone_template"
)
<div class="clearfix">
<div class="input">
<a class="addPhone btn success">Add a phone number</a>
</div>
</div>
</div>
</div>
}
@main(title, nav = "contact") {
@if(contactForm.hasErrors) {
<div class="alert-message error">
<p><strong>Oops</strong> Please fix all errors</p>
</div>
}
@helper.form(action = routes.Contacts.submit, 'id -> "form") {
<fieldset>
<legend>General informations</legend>
@inputText(
contactForm("firstname"),
'_label -> "First name"
)
@inputText(
contactForm("lastname"),
'_label -> "Last name"
)
@inputText(
contactForm("company"),
'_label -> "Company"
)
</fieldset>
<fieldset>
<legend>Profiles</legend>
<div id="profiles">
@repeat(contactForm("informations")) { information =>
@informationGroup(information)
}
@**
* Keep an hidden block that will be used as template for Javascript copy code
**@
@informationGroup(
contactForm("informations[x]"),
className = "profile_template"
)
<div class="manage">
<a class="addProfile btn success">Add another profile</a>
</div>
</div>
</fieldset>
<div class="actions">
<input type="submit" class="btn primary" value="Insert">
<a href="@routes.Application.index" class="btn">Cancel</a>
</div>
}
The code is supposed to render a view like this
By pressing the add phone number some filed are added to the form and it'll become like this :
what make me really confused about this code is these parts and how they work :
@phoneField(field: Field, className: String = "phone") = {
@input(field, '_label -> "Phone numbers", '_class -> className) { (id, name, value, _) =>
<input type="text" name="@name" value="@value">
<a class="removePhone btn danger">Remove</a>
}
}
and
@repeat(field("phones"), min = 0) { phone =>
@phoneField(phone("number"))
}
@**
* Keep an hidden block that will be used as template for Javascript copy code
**@
@phoneField(
field("phones[x].number"),
className = "phone_template"
)
Can someone please provide me a brief explanation about how these lines of codes work, and please don't put links to short tutorials on blogs or websites to Scala I can find them myself with a Google search
I am just looking for a short but descriptive explanation about these lines of codes, thanks in advance!!
btw I dropped out the javascript codes from original code
Let's start with the @phoneField
function:
@phoneField(field: Field, className: String = "phone") = {
@input(field, '_label -> "Phone numbers", '_class -> className) { (id, name, value, _) =>
<input type="text" name="@name" value="@value">
<a class="removePhone btn danger">Remove</a>
}
}
@input
is a helper (i.e. function) that allows you create html for the field yourself. This is needed in this context because we want to add .removePhone
button. So @phoneField
simply takes instance of Field
and constructs html input and remove-link.
Now, what about @repeat
?
@repeat(field("phones"), min = 0) { phone =>
@phoneField(phone)
}
In the app/controllers/Contacts.scala defined contactForm and there you can see that "phones" field defined as list(text). It is a sort of collection with elements that are text fields.
So @repeat will iterate over field("phones")
and pass each text field to the @phoneField
. Important thing that all fields that will go to @phoneField will have names like "phones[0]", "phones1", ....
Now things got interesting.
@phoneField(
field("phones[x]"),
className = "phone_template"
)
constructs a template for the javascript function that will copy it's content to the page on response to "add phone field" button. Looks like field("phones[x]")
constructs empty field with name "phones[x]" similar to what @repeat
is generating. Then whole construct will create a phone field (and remove-link) with name "phones[x]" and empty value.
When you'll look at the javascript code you will see that when user clicks "Add a phone number" link javascript callback will be executed that will copy the html from the template to the dom under <div class="phones">
, and will renumber all .phone input which name matches /phones\[.+\]/
I hope that you have read Using the form template helpers.