4

I am working with jsf Mojarra 2.2.7, Java 8, Primefaces 5.1 and netbeans 8.0.2

I have a class Event with a property List<GameRecord> gameRecordList. GameRecord includes List<Boolean> gamesEntered and other properties. The idea is I have a list of people in an event and am configuring if they are entered into bets or competitions.

In my .xhtml file I have

<p:dataTable value="#{events.gameRecordList}" var="item" rowIndexVar="rowIndex">

                <p:column>#{item.field1}</p:column>
                <p:column>#{item.field2}</p:column>

                <c:forEach items="#{events.gameRecordList.get(rowIndex).gamesEntered}" var="game">
                    <p:column>
                        <p:selectBooleanCheckbox value="#{game}"/>
                    </p:column>
                </c:forEach>


            </p:dataTable>

The <c:forEach> should work with value="#{item.gamesEntered}" rather than the full string but it does not. I have tried <ui:repeat> but either way the page comes up blank where this data should have appeared.

Does this make sense or is there a reason the full addressing is required to make it work?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
GolfAddict
  • 183
  • 3
  • 15
  • Where is this full string? I don't see it. And you cannot use the variable of a jsf component (rowIndex) in jstl tags. See http://stackoverflow.com/questions/4154841/mixing-jsf-tags-with-jstl-tags-gives-strange-results – Kukeltje Mar 13 '15 at 09:11

1 Answers1

8

The <c:forEach> should work with value="#{item.gamesEntered}" rather than the full string but it does not.

JSTL tags run during view build time, building JSF component tree. JSF components run during view render time, producing HTML output. So at the moment <c:forEach> runs, <p:dataTable> hasn't run and its var is nowhere available and will evaluate as null. Note that the same applies to rowIndexVar, which will evaluate as 0 (the default value of an int).

See also


I have tried <ui:repeat> but either way the page comes up blank where this data should have appeared.

UIData components can only accept UIColumn children. The <ui:repeat> isn't such one. The <c:forEach> works because it basically produces a bunch of physical <p:column> components for the datatable. You're lucky that each item has apparently the same amount of gamesEntered as the first item, this would otherwise have failed hard as well.

See also:


By the way, you need <p:columns> which is basically an <ui:repeat> which extends from UIColumn class. But also here, its value cannot be set on a per-row basis, only on a per-table basis. The rowIndexVar isn't available in <p:columns value> and would evaluate as 0 anyway.

<p:dataTable value="#{events.gameRecordList}" var="item" rowIndexVar="rowIndex">
    <p:column>#{item.field1}</p:column>
    <p:column>#{item.field2}</p:column>
    <p:columns value="#{events.gameRecordList[0].gamesEntered}" columnIndexVar="columnIndex">
        <p:selectBooleanCheckbox value="#{events.gameRecordList[rowIndex].gamesEntered[columnIndex]}"/>
    </p:columns>
</p:dataTable>

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Makes perfect sense. Thank you! – GolfAddict Mar 14 '15 at 14:14
  • I've made the changes and it presents fine but the properties do not update when the user makes changes. Being a List I do not have setters for the indexes and am not sure how to debug other than to post the code to find out what I did wrong. Should I post the final code here or open a new question? – GolfAddict Mar 14 '15 at 17:44
  • Sorry, I missed the comment, I've updated the answer. – BalusC Mar 17 '15 at 07:25
  • I needed to add the mandatory var attribute to the p:columns but I got it working by your suggestion. However I am not sure if I understand this correctly or if it is just fooling the view render parser. The [0] reference in p:columns value isn't the row reference but rowIndex in the next line is. Am I just getting away with your detailed knowledge of the current process or is this a sustainable approach? – GolfAddict Mar 17 '15 at 16:34
  • That's because columns are (and can only be) definied on a per-table basis, not on a per-row basis. While columns are created, the p:dataTable hasn't iterated yet and the rowIndex would default to 0 anyway. Think of it like the c:forEach approach. The "See also" links below will elaborate it further and give other examples. You'll now perhaps also better understand my "You're lucky" remark in ui:repeat. – BalusC Mar 17 '15 at 16:43
  • I have read every link, the primefaces showcase examples etc. but your comment that rows need to be defined at a table level vs row is actually my intent. The challenge is the dynamic nature of the columns needed. I keep track of games for an event and the games players are registered for. Before calling this page I build a mask of all games for all players marking them true or false so that I have a consistent number of columns. The gameList provides the headers, the GameRecord the players and gamesEntered the enrollment of each game. gameList and gamesEntered will ALWAYS be of the same size – GolfAddict Mar 17 '15 at 17:16
  • Okay. By the way, given that everything is of same size, have you considered a `` instead? This might only require a change in the model (no booleans, but true entities possible), however it should end up in a more intuitive view (and perhaps also model if you actually don't want booleans but only collections/FK-relationships, the more so if you're actually manually mapping between booleans and existing relationships). – BalusC Mar 17 '15 at 17:18
  • I'm familiar but have never used it. My assumption was that it couldn't handle the headers and formatting I needed but I'll investigate and change if it can provide a better answer. Thanks again for all of your help!! – GolfAddict Mar 17 '15 at 17:25