I've actually found quite a bit on this in various different forums, but none of them appear to have worked for me. My problem isn't even that complicated, but I can't figure out why it's not working. I've set up my datatable so that it's editable and set the editMode="cell". I set up the ajax event and it fires, but the new and old values are always null.
When I'm finished editing a cell and go to the next cell, the cell goes back to the old value. When I click back into it, it shows the new value. Both the outputLabel and inputText tags use the exact same variable, but they are not showing the same value. I've tried manually updating the table manually through the method call as well and that does nothing. Also tried putting a p:ajax tag inside the inputText tag to update the table and that didn't work either.
Here's my JSF code:
<p:dataTable id="dynamicTable" value="#{column.values}" var="value" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="bean.updateCell" immediate="true" update=":dynamicTable"/>
<p:columns value="#{bean.columns}" var="column">
<f:facet name="header">
<p:outputLabel value="#{column.name}"/>
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:outputLabel value="#{value}"/></f:facet>
<f:facet name="input"><p:inputText value="#{value}"/></f:facet>
</p:cellEditor>
</p:columns>
</p:dataTable>
Here's my bean:
@ManagedBean(name = "bean")
@ViewScoped
public class Bean implements Serializable {
private ArrayList<Column> columns;
public ArrayList<Column> getColumns(){
return columns;
}
public void setColumns(ArrayList<Column> columns){
this.columns = columns;
}
@PostConstruct
void init(){
columns = new ArrayList<>();
Column column = new Column();
column.setName("Acronym");
ArrayList<String> values = new ArrayList<>();
values.add("KFC");
values.add("TTYL");
values.add("BRB");
column.setValues(values);
columns.add(column);
column = new Column();
column.setName("Meaning");
values = new ArrayList<>();
values.add("Kentuky Fried Chicken");
values.add("Talk to you later");
values.add("Be right back");
column.setValues(values);
columns.add(column);
}
public void updateCell(CellEditEvent event){
System.out.println((String) event.getNewValue();
}
}
And my Column class:
public class Column{
private ArrayList<String> values;
private String name;
public ArrayList<String> getValues(){
return values;
}
public void setValues(ArrayList<String> values){
this.values = values;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
I rewrote the code to not include sensitive information and renamed variables, so if I'm missing something it's possible that I already have it in my code, but have accidentally removed it.
It turns out the way I was doing the p:columns tag was incorrect. After I made the following changes my problem was solved.
I've made an additional class called TableRow with various String objects to signify the columns to be used. Here's the new code:
JSF:
<p:dataTable id="dynamicTable" value="#{bean.tblRows}" var="row" editable="true" editMode="cell">
<p:columns value="#{bean.columns}" var="column">
<f:facet name="header">
<p:outputLabel value="#{column.name}"/>
</f:facet>
<p:cellEditor>
<f:facet name="output"><p:outputLabel value="#{row[column.variable]}"/></f:facet>
<f:facet name="output"><p:inputText value="#{row[column.variable]}"/></f:facet>
</p:cellEditor>
</p:columns>
</p:dataTable>
Bean:
@ManagedBean (name = "bean")
@ViewScoped
public class Bean implements Serializable {
private ArrayList<TableRow> tblRows;
private ArrayList<Column> columns;
public ArrayList<TableRow> getTblRows(){
return tblRows;
}
public void setTblRows(ArrayList<TableRow> tblRows){
this.tblRows = tblRows;
}
public ArrayList<Column> getColumns(){
return columns;
}
public void setColumns(ArrayList<Column> columns){
this.columns = columns;
}
@PostConstruct
void init(){
columns = new ArrayList<>();
columns.add(new Column("Acronym", "col1");
columns.add(new Column("Meaning", "col2");
tblRows = new ArrayList<>();
tblRows.add(new TableRow("KFC", "Kentuky Fried Chicken"));
tblRows.add(new TableRow("TTYL", "Talk to you later"));
tblRows.add(new TableRow("BRB", "Be right back"));
}
}
TableRow Class:
public class TableRow {
private String col1;
private String col2;
public TableRow(String col1, String col2){
this.col1 = col1;
this.col2 = col2;
}
public String getCol1(){
return col1;
}
public void setCol1(String col1){
this.col1 = col1;
}
public String getCol2(){
return col2;
}
public void setCol2(String col2){
this.col2 = col2;
}
}
Column Class:
public class Column {
private String name;
private String variable;
public Column(String name, String variable){
this.name = name;
this.variable = variable;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getVariable(){
return variable;
}
public void setVariable(String variable){
this.variable = variable;
}
}
The reason why I did "col1" and "col2" instead of give distinct variable names is that the user can choose the column header names so I won't know what to name the variables ahead of time. I was wondering if anyone would like to enlighten me how I could handle this dynamically a little better. When the bean is initialized I don't know how many columns there are going to be or what the column names are going to be.