I have a dynamically expansible table with an add and remove button:
<h:form>
<h:dataTable id="tblFields" value="#{bean.fields}" var="field">
<h:column>
<h:inputText value="#{field.value}" />
</h:column>
<h:column>
<h:inputText value="#{field.value2}" />
</h:column>
<h:column>
<h:inputText value="#{field.value3}" />
</h:column>
<h:column>
<h:commandButton value="Remove">
<f:ajax listener="#{bean.onButtonRemoveFieldClick(field)}" immediate="true" render="@form" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Add">
<f:ajax listener="#{bean.onButtonAddFieldClick}" execute="@form" render="tblFields" />
</h:commandButton>
</h:form>
This is the associated backing bean:
@Named
@ViewScoped
public class Bean {
private List<Field> fields;
@PostConstruct
public void init() {
fields = new ArrayList();
fields.add(new Field());
}
public List<Field> getFields() {
return fields;
}
public void setFields(List<Field> fields) {
this.fields = fields;
}
public void onButtonRemoveFieldClick(Field field) {
fields.remove(field);
}
public void onButtonAddFieldClick() {
fields.add(new Field());
}
}
The use case is as follows:
After that, all values filled so far disappears and show up blank. How can I keep them filled after pressing the remove button?
It's because you're in the remove button ajax-updating the entire form without processing the newly submitted input values. The immediate="true"
on ajax listener skips the processing of all input components which do not have immediate="true"
set. You need to remove the attribtue. The absence of execute
attribute will cause only the current component (@this
) to be processed by default. You need to explicitly specify @form
.
So, just do the same as in your add button. Replace immediate="true"
by execute="@form"
.
<f:ajax listener="#{bean.onButtonRemoveFieldClick(field)}" execute="@form" render="@form" />