当前位置: 首页 > 面试题库 >

在Java中使用Playframework时的父/子表单

丁灿
2023-03-14
问题内容

我有一个“问题”实体,其中有一个“答案”,其中包含“替代品”列表,如下所示:

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;
}

我想制作一个表格以供用户填充问题列表。我读了太多的材料和SO问题,但是我不知道如何正确地处理表单。我知道可以使用DynamicForms以其他方式执行此操作,这不是我想要的。我的想法是可以通过以下方式完成:

@(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>


}

但是,当我尝试使用Answer对象并将其“替代”使用NullPointerexception时,我的脸上会大爆炸:

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

我想念更多有关它和其他相关内容的文档和示例。即使是官方网站也没有提供大量示例。特别是在处理Java时。这给人以为该框架已经过时或被其他技术取代的想法?

我使用Play版本2.4.6。


问题答案:

此处记录了这一点,特别是在处理重复值方面。当然,文档总是可以改进的。请打开一个引发此问题的问题。而且,这并不表示该框架已过时或被其他人所取代(实际上,Play 2.5即将发布且社区正在增长)。

无论如何,这是一个有关如何完成您描述的父母/子女表格的综合示例。请记住,我不在乎样式的样式。

您的域层次结构:

models/Question.java

package models;

public class Question {
    public String text;
    public String sourceCode;
    public String complement;
    public Answer answer;
}

models/Answer.java

package models;

import java.util.List;

public class Answer {
    public List<Alternative> alternatives;
}

models/Alternative.java

package models;

public class Alternative {
    public boolean correct;
    public String statement;
}

控制器和路线:

现在,我有以下操作,该操作仅将Question对象及其子对象作为JSON返回(因为我们只对如何提交此类数据感兴趣):

package controllers;

import models.Question;
import play.data.Form;
import play.libs.Json;
import play.mvc.*;

import views.html.*;

import static play.data.Form.form;

public class Application extends Controller {

    public Result index() {
        Form<Question> form = form(Question.class);
        return ok(index.render(form));
    }

    public Result post() {
        Form<Question> form = form(Question.class).bindFromRequest();
        Question question = form.get();
        return ok(Json.toJson(question));
    }
}

请注意index操作中如何声明a
Form<Question>并将其作为参数传递给视图。您可以在docs上查看有关如何定义表单的更多信息。让我们看看我们的路线:

GET     /                  controllers.Application.index()
POST    /save              controllers.Application.post()

表单视图:

最后,我们需要创建将填充并提交数据的表单:

@(questionForm: Form[Question])

@main("Welcome to Play") {
  @helper.form(action = routes.Application.post()) {
    <h2>Question:</h2>
    @helper.inputText(questionForm("text"))
    @helper.inputText(questionForm("sourceCode"))
    @helper.inputText(questionForm("complement"))
    <h3>Answers:</h3>
    @helper.repeat(questionForm("answer.alternatives"), min = 2) { alternative =>
      @helper.checkbox(alternative("correct"))
      @helper.inputText(alternative("statement"))
    }
    <button type="submit">Save</button>
  }
}

基本上,表单是使用表单助手创建的,该助手将处理表单工作方式的大部分方面(例如按实例显示错误)。特别注意@helper.repeat标记:它将创建以下标记(省略不相关的部分):

<h3>Answers:</h3>

<label>answer.alternatives.0.correct</label>
<input type="checkbox" name="answer.alternatives[0].correct" value=""/>

<label>answer.alternatives.0.statement</label>
<input type="text" name="answer.alternatives[0].statement" value=""/>



<label>answer.alternatives.1.correct</label>
<input type="checkbox" name="answer.alternatives[1].correct" value="" />

<label>answer.alternatives.1.statement</label>
<input type="text" name="answer.alternatives[1].statement" value=""/>

请注意,参数是如何命名的以表示顺序以及alternative对象的相关不同字段。

提交表格:

最后,填写并提交表单后,您将获得以下JSON:

{
  "text": "Question text",
  "sourceCode": "Question source",
  "complement": "Question complement",
  "answer": {
    "alternatives": [
      {
        "correct": true,
        "statement": "Statement 1"
      },
      {
        "correct": false,
        "statement": "Statement 2"
      }
    ]
  }
}


 类似资料:
  • 问题内容: 我有一个“ ChildClass”类,它扩展了“ ParentClass”类。我不想完全替换父类的构造函数,而是要先调用父类的构造函数,然后再做一些额外的工作。 我相信默认情况下会调用父类的0参数构造函数。这不是我想要的 我需要用参数调用构造函数。这可能吗? 我试过了 但这不起作用,因为您无法修改“ this”。 问题答案: 您可以从子代的构造函数中以“ super”引用父代的构造函数

  • 现在,当我们知道提交给的工作是一个长时间运行的操作时,我们需要传递一个自定义执行器(否则默认情况下它将在上执行)。 每个控制器执行都有一个上下文,其中包含所有请求信息。如果使用,······ 如果我们只是创建自定义的并将其注入到控制器中,以便在中使用,那么我们将不会拥有所有的上下文信息。 下面是返回的某个控制器操作的示例 } 如果我们尝试在中运行类似的内容 使用CompletableFuture和

  • 在文档的这一部分中,他们解释了如何为 当您使用时,这是什么等价物: 当使用和时,我们如何确保上下文可用?

  • 我想使用SourceQueue将元素动态推送到Akka流源中。Play controller需要一个源,以便能够使用方法对结果进行流式传输。 由于Play使用自己的Akka流接收器,所以我无法使用接收器来实现源队列,因为源在方法使用之前就会被消耗(除非我使用下面的hack)。 如果我使用reactive-streams发布器预物化源队列,我就可以使它正常工作,但这是一种“肮脏的攻击”: 有没有更简

  • 问题内容: 我对Playframwork已过时的问题有一个烦人的问题,我想将conde移入建议的方式,但是实际上我无法完成此任务,文档没有意义,而且我也不知道如何解决此问题,我花了几天时间数天试图使它没有运气! https://www.playframework.com/documentation/2.5.x/GlobalSettings 我只想运行初始数据库方法 这是java文件中的内部方法,我