First time using JSF, and I’m sort of confused about how getRowData() works. All I found while searching around the internet is that it returns the “currently selected row” in a data table, but I couldn’t find out how it decides which row is the selected one. For example, I have this code for a data table:
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>
Backing 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());
}
}
This makes it so that whenever I click the button in whichever row, the text of all buttons changes to the value in the first column of that row. How exactly does getRowData() know which row to fetch from the table?
Bonus question: why does every button’s text change?
The JSF tags cause a component tree to be built in memory. For example, the
dataTabletag is backed by a UIData instance (of whichHtmlDataTableis a subclass). The role ofUIDatais to iterate over a DataModel. For each phase of the JSF lifecycle, it will do something like this:In your case, the
var="cdto", which is why any controls that use EL to resolve to the row bean will get the correct value.When the component tree is built,
UIDatadoes not add another child control per row. It uses one set of controls and changes the underlying model data. Although theUIDataperforms some actions to preserve child state, it will not do so (by default) for instances of HtmlCommandButton because it does not implement EditableValueHolder.To fix this issue, use an EL expression to bind the value to your model (probably some row bean property).
Note: you can generally avoid having to write code where you have to import any
javax.faces...classes into your model beans, but you have to put a bit of thought into your model design.