实现此功能的自然 JSF 方法是什么?

What is the natural JSF way to inplement this?

我正在学习 JSF2 并且对以下问题感到困惑。我需要实现某种形式,我可以在其中提供可变数量的标记。 比如说,有一个小组,其中有一个学生。学生学习一些科目并获得分数。不同的小组可以有 10 到 30 名学生。 表格应包含一份学生名单,每个学生都有标记字段。 我看到了一些问题:

  1. 如何呈现字段数量可变的表单?
  2. 如何将标记传递给 managedBean?
  3. 我怎样才能将一个学生与另一个学生区分开来?

更新 关于数据模型的解释。 有以下 Entity-classess:PersonStudyCardStudyGroupSubjectMonthMarkPerson 表示字段,对于某些人(姓名、生日等)来说是不变的。 StudyCard代表个人名片之类的东西。它有许多字段,包括与 Person (@ManyToOne) 和 StudyGroup (@ManyToOne) 的关系:

@Entity
@Table(name = "cards")
public class StudyCard implements Serializable {

. . . // fields

@ManyToOne
@JoinColumn(name = "crd_grpcode")
private StudyGroup group;

@ManyToOne
@JoinColumn(name = "crd_psncode", nullable = false)
private Person person;

. . . //getters, setters 
}

StudyGroup是组表示。 Subject - 它表示学生将获得分数的科目。 MonthMark - 它表示学生的学科分数。 t 将包含月、年、主题、studyCard 和标记:

@Entity
@Table(name = "monthmarks")
public class MonthMark implements Serializable {

  @Id
  @Column(name = "mmk_pcode")
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private int id;

  @Column(name = "mmk_month", nullable = false)
  private int month;

  @Column(name = "mmk_year", nullable = false)
  private int year;

  @Column(name = "mmk_mark", nullable = false)
  private int mark;

  @ManyToOne
  @JoinColumn(name = "mmk_subcode")
  private Subject subject;

  @Transient
  private int subjectCode;

  @ManyToOne
  @JoinColumn(name = "mmk_psncode")
  private Person person;

  @Transient
  private int personCode;

  @ManyToOne
  @JoinColumn(name = "mmk_crdcode")
  private StudyCard card;

  @Transient
  private int cardCode;

  . . . // getters, setters, etc
}

在ManagedBean中,我想,会有一个StudyGroup对象,一个Subject对象,我想还有List。

我认为近似的 xhtml 布局会像

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core">

  <f:metadata>
    <f:viewParam name="groupId" value="#{monthMarksMB.groupCode}" />
    <f:viewAction action="#{monthMarksMB.preparePage()}" />
  </f:metadata>  

  <ui:composition template="/WEB-INF/templates/main.xhtml">
    <ui:define name="content">
      <h2>Marks for a month</h2>
      <h:form>
        <h:outputText value="Subject" /><br />
        <h:selectOneMenu value="#{monthMarksMB.subjectCode}"
                           valueChangeListener="#{monthMarksMB.changeSubject}">
          <f:selectItem itemLabel="---select subject---" itemValue="0" />
          <f:selectItems value="#{monthMarksMB.subjectsForGroup}" var="sub" 
                           itemLabel="#{sub.name}" itemValue="#{sub.id}" />
          <f:ajax event="change" execute="@form" render="@form globalMessages" />
        </h:selectOneMenu><p />
        <h:outputText value="Year" /><br />
        <h:inputText value="#{monthMarksMB.year}" class="textEdit" /><p />
        <h:outputText value="Month" /><br />
        <h:inputText value="#{monthMarksMB.month}" class="textEdit" /><p />

        <!-- And now I confused: how implement list of persons and marks?
        something like
        <ui:repeat ...>
          <h:outputText value="person fullname" />
          <h:inputText value="what should be here?" /><br />
        </ui:repeat> 
        -->

        <div class="buttons">
          <h:commandButton value="Сохранить" action="#{monthMarksMB.save()}" />
          <h:commandButton value="Отменить" action="#{monthMarksMB.cancel()}" />
        </div>
      </h:form>
    </ui:define>
  </ui:composition>
</html>

在此表格中,每个人只有一个 MonthMark。在菜单中选择 Subject 将导致更新列表 MonthMarks。如果标记已经存在 - 我希望显示它以更正它。如果还没有MonthMarks,应该是一个空字段用于输入标记保存。

所以,我向 JSF 专家寻求帮助。此实现的 JSF 自然方式是什么? 最好的问候。

所以,我已经尝试过并且看起来很有效。我做了一些简单的测试 xhtml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
  <h:head>
    <title>JSF incubator</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  </h:head>
  <h:body>
    <h:panelGroup rendered="#{testMB.edit}">
      <h2>Edit marks</h2>
      <h:form>
        <h:selectOneMenu value="#{testMB.subjectCode}" valueChangeListener="#{testMB.changeSubject}">
          <f:selectItem itemLabel="---Select---" itemValue="0" />
          <f:selectItem itemLabel="Computer skills" itemValue="1" />
          <f:selectItem itemLabel="Phylosofy" itemValue="2" />
          <f:selectItem itemLabel="Foreign languages" itemValue="3" />
          <f:selectItem itemLabel="Mathematics" itemValue="4" />
          <f:ajax execute="@this" render="@form" />
        </h:selectOneMenu>
        <p>
        <ui:repeat value="#{testMB.marks}" var="mark">
          <h:outputText value="#{mark.person} " />
          <h:inputText value="#{mark.mark}" /><br />
        </ui:repeat>
        </p>
        <p>
          <h:commandButton value="Save" action="#{testMB.save()}" />
        </p>
      </h:form>
    </h:panelGroup>
    <h:panelGroup rendered="#{not testMB.edit}">
      <h2>Show marks</h2>
        <p>
        <ui:repeat value="#{testMB.marks}" var="mark">
          <h:outputText value="#{mark.person} " />
          <h:outputText value="#{mark.mark}" /><br />
        </ui:repeat>
        </p>
      <h:form>
        <p>
          <h:commandButton value="Edit" action="#{testMB.change()}" />
        </p>
      </h:form>
    </h:panelGroup>
  </h:body>
</html>

和 TestMB 托管 bean:

@ManagedBean(name = "testMB")
@ViewScoped
public class TestMB {

  private int subjectCode;
  private List<Mark> marks;
  private boolean edit;

  @PostConstruct
  private void initData() {
    edit = true;
  }

  public void save() {
    edit = false;
  }

  public void change() {
    edit = true;
  }

  public void changeSubject(ValueChangeEvent event) {
    try {
      int code = (Integer) event.getNewValue();
      if (code > 0) {
        marks = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
          marks.add(new Mark(0, code, "Person" + i));
        }
      }
    } catch (Exception e) {
      addMessage("somethind wrong!");
    }
  }

  public List<Mark> getMarks() {
    return marks;
  }

  public int getSubjectCode() {
    return subjectCode;
  }

  public void setSubjectCode(int subjectCode) {
    this.subjectCode = subjectCode;
  }

  public boolean isEdit() {
    return edit;
  }
}

比我想象的要简单。我希望,我了解如何在实际细节上实现这一点。 感谢您浪费您的时间。