I have a "Question" entity that has a "Answer" that has a list of "Alternatives" as below:
public class Question extends BaseEntity {
private String text;
private String sourceCode;
private String complement;
private Answer answer;
}
public class Answer extends BaseEntity{
private List<Alternative> alternatives;
}
I want to make a form to user populate with a list of questions. I read so many material and SO questions, but I cannot get how to do exactly what I want with forms. I know that I can do it in other manner using DynamicForms, this is not what I want. My idea is that it could be done this way:
@(message: String, form: play.data.Form[Question])
@main("cadastrar questão") {
<script src="@routes.Assets.at("javascripts/index.js")"></script>
<div class="page-header">
<h1>@message</h1>
</div>
<body>
<style>
.top-buffer { margin-top:12px ; }
</style>
<div class="container.fluid form-group">
@helper.form(routes.Application.submit()) {
<div class="row top-buffer">
<label for="text">Enunciado:</label>
<textarea id="text" name="text" class="form-control col-md-6" placeholder="Enunciado da questão" rows="5" value="@form("text").value()"></textarea>
</div>
...
<div class="row top-buffer">
<label for="complement">Corretas:</label>
<input type="text" name="correct" class="form-control col-md-6" value="@form("complement.answer.alternatives[0]").value()">
</div>
<div class="row top-buffer">
<div class="row top-buffer">
<input type="submit" class="btn btn-primary col-md-1" value="submit">
</div>
</div>
}
</div>
</body>
}
But when I try to use the Answer object and it "Alternatives" a big NullPointerexception
explodes on my face:
final Form<Question> questionForm = f.bindFromRequest();
final Question question = questionForm.get();
System.out.println(question);
System.out.println(question.getText());
System.out.println(question.getSourceCode());
System.out.println(question.getComplement());
//Nullpointer here:
final List<Alternative> alternatives =
question.getAnswer().getAlternatives();
alternatives.forEach(p -> System.out.println(p));
I miss more documentation and examples about it and other things related. Even the official website does not provide extensive examples. Especially when dealing with Java. This gives an idea that the framework is becoming obsolete or being overtaken by other technologies?
I use version 2.4.6 of Play.
This is documented here, specifically at how to handle repeated values. Of course, documentation can always be improved. Please open an issue raising this problem. Also, this does not represent that the framework is becoming obsolete or being overtaken by others (in fact, Play 2.5 is close to being released and the community is growing).
Anyway, here is an comprehensive example about how to do a parent/child form like you described. Keep in mind that I didn't care about styling the forms.
Your domain hierarchy:
models/Question.java
:models/Answer.java
:models/Alternative.java
:Controllers and routes:
Now, I have the following action that just returns the
Question
object and its children as a JSON (since we are just interested in how to submit this kind of data):Notice at the
index
action how I've declared aForm<Question>
and passed it as an argument to the view. You can see more information about how to define a form at the docs. Let's see our routes:The form view:
Finally, we need to create the form that will populate and submit the data:
Basically the form was created using the form helpers which will handle most of the aspects of how the form works (like showing errors, per instance). Special attention to the
@helper.repeat
tag: it will create the following markup (omitting irrelevant parts):Notice how the parameters are named to represent an order and also related different fields of the
alternative
object.Submitting the form:
Finally, after filling and submitting the form, you will get the following JSON: