JSF resets fields when doing an ajax update

ajax, jsf-2

Solution

The `<f:ajax>` processes by default only the current component as in `execute="@this"`. So the submitted values of all other input components won't be processed and thus not be updated into the model. However, you're by `render="@form"` forcing the entire HTML output of the form to be refreshed with current (non-updated!) model values of all other input components.

Assuming that your intent is to not unnecessarily convert/validate/update all other input components, you'd better make the `render` attribute more specific. Update only the content which really needs to be updated and not the entire form.

<p:selectBooleanCheckbox value="#{addressBean.copyBillingAddress}" id="duplicateBillingDetails">
    <f:ajax render="copyBillingAddress" />
</p:selectBooleanCheckbox>

<h:panelGroup id="copyBillingAddress">
    <h:panelGrid rendered="#{not addressBean.copyBillingAddress}" columns="3">
        <p:inputText value="#{addressBean.deliveryAddress.firstName}"/>
    </h:panelGrid>
</h:panelGroup>

Or, if you really need the `render="@form"`, then you need to add a `execute="@form"` in order to tell `<f:ajax>` to process all other input components as well.

<f:ajax execute="@form" render="@form" />

Note that this may unnecessarily trigger conversion/validation on those input components.

See also:

- Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

Problem

I have a problem on my JSF page where I type a name into the first billing first name field. If I click on copy billing address checkbox; this stops rendering the delivery address panel and hides it via ajax, the value I just typed into the first field gets reset to its previous state. JSF Page ``` <h:form> <p:inputText value="#{addressBean.billingAddress.firstName}" required="true"/ > <p:selectBooleanCheckbox value="#{addressBean.copyBillingAddress}" id="duplicateBillingDetails"> <f:ajax render="@form" /> </p:selectBooleanCheckbox> <h:panelGrid rendered="#{not addressBean.copyBillingAddress}" columns="3"> <p:inputText value="#{addressBean.deliveryAddress.firstName}"/> </h:panelGrid> <p:commandButton value="Checkout" action="#{addressBean.saveAddress}"/> </h:form> ``` Backing Bean ``` @Component @Scope("view") public class AddressBean implements Serializable { @Inject private CurrentUserBean currentUserBean; @Inject private UserService userService; private Address deliveryAddress = new Address(); private Address billingAddress = new Address(); private boolean copyBillingAddress; public AddressBean() { } public boolean isCopyBillingAddress() { return copyBillingAddress; } public void setCopyBillingAddress(boolean copyBillingAddress) { this.copyBillingAddress = copyBillingAddress; } public String saveAddress() { if (copyBillingAddress) { deliveryAddress = new Address(billingAddress); } User user = currentUserBean.getUser(); if (!billingAddress.isSame(user.getBillingAddress())) { user.setBillingAddress(billingAddress); } if (!deliveryAddress.isSame(user.getDeliveryAddress())) { user.setDeliveryAddress(deliveryAddress); } currentUserBean.setUser(userService.save(user)); return "/checkout.xhtml"; } public CurrentUserBean getCurrentUserBean() { return currentUserBean; } public void setCurrentUserBean(CurrentUserBean currentUserBean) { this.currentUserBean = currentUserBean; } public Address getDeliveryAddress() { return deliveryAddress; } public void setDeliveryAddress(Address deliveryAddress) { this.deliveryAddress = deliveryAddress; } public Address getBillingAddress() { return billingAddress; } public void setBillingAddress(Address billingAddress) { this.billingAddress = billingAddress; } } ```

Original source

Related problems