I need to create a table where the headers list are brought from a model. The table contents are also stored in the model and p:dataTable loop on the data to show the conten
The input component's value must be bound to a writable value expression. What you've there is a direct getter method invocation and thus essentially read-only. This is indeed not going to work. You need to specify a property name of the #{entity}
. You can use the brace notation to specify the property name as a variable like so #{entity[propertyName]}
.
So, basically:
<p:dataTable value="#{bean.entities}" var="entity" editable="true" editMode="cell">
<p:columns value="#{bean.propertyNames}" var="propertyNames">
<p:cellEditor>
<f:facet name="output">
#{entity[propertyName]}
</f:facet>
<f:facet name="input">
<p:inputText value="#{entity[propertyName]}" />
</f:facet>
</p:cellEditor>
</p:columns>
</p:dataTable>
As to the column header, rather refactor out that into a Map<String, String>
where the key is the propertyName
and the value is the header.
<f:facet name="header">
#{bean.columnHeaders[propertyName]}
</f:facet name="header">
Or better yet, use a normal i18n resource bundle for that where the propertyName
represents part of the bundle key.
<f:facet name="header">
#{bundle['table.column.header.' += propertyName]}
</f:facet name="header">
As to the editable check, rather wrap propertyName
and editable
in another bean (and perhaps also columnHeader
if you don't want to use a i18n bundle), e.g. Field
and then use like below:
<p:columns value="#{bean.fields}" var="field">
<p:cellEditor>
<f:facet name="output">
#{entity[field.propertyName]}
</f:facet>
<f:facet name="input">
<p:inputText value="#{entity[field.propertyName]}" rendered="#{entity[field.editable]}" />
</f:facet>
</p:cellEditor>
</p:columns>
All in all, it just boils down to preparing and providing the right model the view expects. This way the getData()
thing isn't necessary.