1

I have a Primefaces (5.0) Datatable with dynamic columns as well as dynamic rows. In brief, my problem is how do I set it up so that the cells of the first row are a series of inputText's or inputTextarea's, while the rows below the first are outputText?

To elaborate, the xhtml (following BalusC's response to Creating and populating a DataTable dynamically in JSF2.0) is as follows:

<p:dataTable var="rowMap" value="#{reviewController.rowMapList}" scrollable="true" scrollWidth="900px"  >
            <p:columns value="#{reviewController.columnNameList}" var="columnName" headerText="#{columnName}">
                <f:facet name="header" >#{columnName}</f:facet>
                <f:facet name="header"><p:inputTextarea  value="#{rowMap[columnName]}"  /></f:facet>
                <h:outputText value="#{rowMap[columnName]}"  />
            </p:columns>
        </p:dataTable> 

So I'm thinking, likely there is a problem in using facets for the row with the inputTexts, because the facet doesn't seem to take part in the dataTable data iteration. So how do I put the first row in as a "normal" row (rather than a facet if that is part of the problem) -- but still apply inputTextarea's to that first row, without applying inputTextareas to all the rows?

For the purposes of getting it working, I've set it up statically with a @PostConstruct on reviewController, as follows.

@Named
@ViewScoped
public class ReviewController implements Serializable {

private List<String> columnNameList;
private ArrayList<Map<String, Object>> rowMapList;
private Map<String, Object> rowMap;

@PostConstruct
public void init() {
     columnNameList = new ArrayList<>();
     rowMapList = new ArrayList<>();

     columnNameList.add("Source Report");
     columnNameList.add("Overview");
     columnNameList.add("Question 1");
     columnNameList.add("Question 2");
     columnNameList.add("Question 3");

     Map<String, Object> m = new HashMap<>();
     m.put(columnNameList.get(0), "Assessor1");
     m.put(columnNameList.get(1), "Assessor1 overview text");
     m.put(columnNameList.get(2), "Assessor1 comment on Q1");
     m.put(columnNameList.get(3), "Assessor1 comment on Q2");
     m.put(columnNameList.get(4), "Assessor1 comment on Q3");
     rowMapList.add(m);
     m = new HashMap<>();
     m.put(columnNameList.get(0), "Assessor2");
     m.put(columnNameList.get(1), "Assessor2 overview text");
     m.put(columnNameList.get(2), "Assessor2 comment on Q1");
     m.put(columnNameList.get(3), "Assessor2 comment on Q2");
     m.put(columnNameList.get(4), "Assessor2 comment on Q3");
     rowMapList.add(m);
     //etc
}

Visually it turns out like this:

enter image description here

What I want is to have the first row being a row of InputTextarea's, so the user can add comments in each first row cell in response to the content of the rows beneath it. I've achieved it visually - but as I remark above, it doesn't work in that the inputTextareas (I presume because they're in facets) are not hooked into the rowMap and columnName iterations

I have looked at the primefaces editable datatable (http://www.primefaces.org/showcase/ui/data/datatable/edit.xhtml) - which is somewhat along the lines of what is required. However it makes all rows editable, not just the first. There is the further complexity in this case that both columns and rows will be dynamically applied.

Any comment or assistance appreciated. Thanks.

Community
  • 1
  • 1
anvw
  • 149
  • 3
  • 15
  • Why don't you use m.put(columnNameList.get(0), "input text value"); and use rendered input column when row == 0 else display output text? – Unknown Apr 10 '16 at 13:30
  • Your logic is sound. My question is - how do you build in the condition of "when row==0" into the expression language and xhtml of the xhtml file? How do I modify the xhtml above so that it catches the cells of the first row and modifies it as needed? – anvw Apr 10 '16 at 13:37
  • 1
    You user rowIndexVar="row" of data table () and use rendered="#{row==0}" on the column. – Unknown Apr 10 '16 at 13:41
  • That looks very promising, thank you. Crazy late here but I will try applying it later in the morning. – anvw Apr 10 '16 at 14:05

2 Answers2

2

Since you asked you want only the 1st row is editable, I have asked you to use rowIndexVar to manage the rows.

You can use p:dataTable's rowIndexVar attribute.

rowIndexVar is Name of iterator to refer each row index.

Whose iterator name can be used in EL to get the Row Id

For example: if rowIndexVar="row" then you can access each row Index using that iterator name in EL using #{row}.

Example Code:

<p:dataTable rowIndexVar="row" value="..." var="myVar">
    <p:column>
       <p:inputTextarea rows="2" cols="25" counter="display"
                            value="#{myVar.myText}" rendered="#{row==0}"                       id="comment1"
                            maxlength="200"
                            counterTemplate="{0} remaining characters"
                            autoResize="false">
                        </p:inputTextarea>
        <h:outputText value="#{myVar.myText}" rendered="#{row!=0}" />
    </p:column>
    ....
</p:dataTable>
Unknown
  • 2,037
  • 3
  • 30
  • 47
0

Thank you again to Unknown: This is effectively your answer (I don't know if there is a more formal way of attributing it to you, but I am happy to do so ). Much appreciated. xhtml code as follows:

<p:dataTable var="rowMap" rowIndexVar="row" value="#{reviewController.rowMapList}"   >
            <p:columns value="#{reviewController.columnNameList[0]}" var="columnName" headerText="#{columnName}">
                                        #{rowMap[columnName]}
                                    </p:columns>
            <p:columns value="#{reviewController.columnNameList}" columnIndexVar="col" rendered="#{col!=0}" var="columnName" headerText="#{columnName}" >
                <f:facet name="header" >#{columnName}</f:facet>
                <h:inputTextarea  value="#{rowMap[columnName]}" rendered="#{row==0}" />
                <h:outputText value="#{rowMap[columnName]}" rendered="#{row!=0}" />
            </p:columns>
        </p:dataTable>  

So it is as you described it for the rows, plus I have added an extra p:columns block just to differentiate the first column, and placed a columnIndexVar with rendered="#{col!=0}" conditional on the main p:Columns block so that the first column does not have the inputTextarea that the other cells of the first row do.

anvw
  • 149
  • 3
  • 15
  • 1
    "Formal way" is just asking `@user` in a comment to repost the comment as an answer. More than often, users may post educated guesses or potential answers to ambiguous questions as comments, just to be on the safe side. If it turns out to work out well, more than often the user wouldn't have any problems reposting (and even elaborating) the solution in a real answer. – BalusC Apr 11 '16 at 08:13