getRowData()的精确语义?

时间:2010-11-07 15:23:55

标签: java jsf datatable

第一次使用JSF,我对getRowData()的工作方式感到困惑。我在互联网上搜索时发现的只是它返回数据表中的“当前选定行”,但我无法确定它是如何决定选择哪一行的。例如,我有一个数据表的代码:

JSP:

  <h:dataTable value="#{backing_student.eligibleCoursesList}" var="cdto"
                     binding="#{backing_student.eligibleCoursesDataTable}"
                     id="eligibleCoursesDataTable" rules="all" frame="box"
                     border="2">
  <%-- 
            oracle-jdev-comment:Faces.RI.DT.Class.Key:hu.elte.pgy2.BACNAAI.UranEJB.CourseDTO
          --%>
    <h:column>
      <f:facet name="header">
        <h:outputText value="Kurzuskód"
                      binding="#{backing_student.outputText7}"
                      id="outputText7"/>
      </f:facet>
      <h:outputText value="#{cdto.cid}"/>
    </h:column>
    <!-- couple more plain text columns like the above -->
    </h:column>
    <h:column>
      <h:commandButton value="Felvétel"
                       actionListener="#{backing_student.addSelfToCourseListener}"/>
    </h:column>
  </h:dataTable>

支持bean:

public class BackingStudent {
    private HtmlDataTable eligibleCoursesDataTable;
    private List<CourseDTO> eligibleCoursesList;

    // ...

    public void addSelfToCourseListener(ActionEvent actionEvent) {
        HtmlCommandButton thisButton = (HtmlCommandButton)actionEvent.getComponent();
        CourseDTO cdto = (CourseDTO)(eligibleCoursesDataTable.getRowData());
        thisButton.setValue(cdto.getCid());
    }
}

这使得无论何时单击任何行中的按钮,所有按钮的文本都将更改为该行第一列中的值。 getRowData()究竟知道要从表中获取哪一行?

奖金问题:为什么每个按钮的文字都会改变?

2 个答案:

答案 0 :(得分:3)

JSF标记导致组件树在内存中构建。例如,dataTable标记由UIData实例(其中HtmlDataTable是子类)支持。 UIData的作用是迭代DataModel。对于JSF lifecycle的每个阶段,它将执行以下操作:

//not the real code
for(int i=0; i<model.getRowCount(); i++) {
  model.setRowIndex(i);
  Object row = model.getRowData();
  externalContext.getRequestMap().put(var, row);
  //invoke phase-specific action
  externalContext.getRequestMap().remove(var);
}

在您的情况下,var="cdto",这就是使用EL解析到行bean的任何控件将获得正确的值。

构建组件树时,UIData不会每行添加另一个子控件。它使用一组控件并更改基础模型数据。虽然UIData performs some actions to preserve child state,但HtmlCommandButton的实例不会这样做(默认情况下),因为它没有实现EditableValueHolder

要解决此问题,请使用EL表达式将值绑定到模型(可能是某些行bean属性)。

注意:您通常可以避免在必须将任何javax.faces...类导入模型bean的情况下编写代码,但是您必须在模型设计中加入一些思考。

答案 1 :(得分:1)

当您单击某一行时,该组件会调用DataModel.setRowIndex(),它会设置所单击行的索引。 DataModel.getRowData()检索DataModel.getRowIndex()引用的行的数据。