Resetting Bean when using Ajax events in PrimeFaces

Viewed 1998

I have a dialog, which contains checkbox and one input field. When this checkbox is checked, input should be disabled. Checkbox value is stored in Bean and input value is one of the selected object values.

This dialog pops up, when user clicks on a link on the list. Dialog's inputs are being populated with values from model.

I have also two buttons: save and cancel. On save, depending on checkbox value, I'm doing different stuff with the model and updating it. On cancel I want to do nothing.

The problem is: when there are ajax events connected with checkbox, value in Bean is automatically updated. So after clicking cancel and reopening the dialog, I got last state, but I want initial state.

Here is the code:

List

<h:form id="termPanelForm">

    <p:dataTable id="termPanelTable"
        value="#{termRightPanelController.terms}" var="term" emptyMessage="">

        <p:column>
            <p:commandLink value="#{term.subject}"
                action="#{termRightPanelController.setTerm(term)}"
                oncomplete="termRealizeDlg.show();"
                update=":termRealizeForm:termRealizeDialog" />
        </p:column>

        <p:column width="50">
            <h:outputText value="#{term.dateRealization}">
                <f:convertDateTime pattern="dd-MM-yy HH:mm" />
            </h:outputText>
        </p:column>
    </p:dataTable>

</h:form>

Dialog

<h:form id="termRealizeForm">
    <p:dialog id="termRealizeDialog" widgetVar="termRealizeDlg"
        modal="true" resizable="false" closeOnEscape="true"
        header="#{termRightPanelController.selectedTerm.subject}">

        <p:messages autoUpdate="true" showDetail="true"></p:messages>

        <p:panelGrid columns="2" styleClass="border-none">

            <p:outputLabel for="realized" value="#{i18n['Term.MarkRealized']}" />
            <p:selectBooleanCheckbox id="realized"
                value="#{termRightPanelController.termRealized}">
                <p:ajax process="@this" update="dateRealization" />
            </p:selectBooleanCheckbox>

            <p:outputLabel for="dateRealization"
                value="#{i18n['Term.ChangeDateRealization']}" />
            <p:inputText id="dateRealization"
                value="#{termRightPanelController.selectedTerm.dateRealization}"
                pattern="dd-MM-yyyy HH:mm"
                disabled="#{termRightPanelController.termRealized}" >
            </p:inputText>

        </p:panelGrid>

        <h:panelGroup layout="block" styleClass="buttons-group">
            <p:commandButton value="#{i18n['Common.Save']}"
                oncomplete="hideDialogWhenValid(termRealizeDlg, xhr, status, args);"
                action="#{termRightPanelController.editTerm()}"
                update=":termPanelForm:termPanelTable" icon="ui-icon-check"></p:commandButton>
            <p:commandButton onclick="termRealizeDlg.hide();"
                value="#{i18n['Common.cancel']}" 
                icon="ui-icon-cancel" update=":termRealizeForm:termRealizeDialog">
            </p:commandButton>
        </h:panelGroup>

    </p:dialog>
</h:form>

Bean

@SuppressWarnings("rawtypes")
@ManagedBean
@ViewScoped
public class TermRightPanelController extends MainController implements Serializable {

    private static final long serialVersionUID = 6283828584670862366L;

    private TermServiceLocal termService = ServiceLocator.locateService(
            TermService.class, TermServiceLocal.class);

    private List<Term> terms;

    private Term selectedTerm;

    private boolean termRealized;

    @PostConstruct
    public void init() {
        loadTerms();
    }

    public void loadTerms() {
        terms = termService.getTermsNotRealized(getLoggedUser().getId());
    }

    public String expiredTerm(Term term) {
        long time = new Date().getTime();
        if (term.getDateRealization().getTime() > time) {
            return "";
        }

        return "expired";
    }

    public void editTerm() {
        if (termRealized) {
            selectedTerm.setDateRead(new Date());
        } else {
            selectedTerm.setDateRead(null);
        }
        termService.merge(selectedTerm);
        loadTerms();
    }

    public void setTerm(Term term) {
        this.selectedTerm = term;
    }

    public List<Term> getTerms() {
        return terms;
    }

    public void setTerms(List<Term> terms) {
        this.terms = terms;
    }

    public Term getSelectedTerm() {
        return selectedTerm;
    }

    public void setSelectedTerm(Term selectedTerm) {
        this.selectedTerm = selectedTerm;
    }

    public boolean isTermRealized() {
        return termRealized;
    }

    public void setTermRealized(boolean termRealized) {
        this.termRealized = termRealized;
    }

    @Override
    public Class getModelClass() {
        return this.getClass();
    }
}

In this particular scenario, I can always set termRealized to false when I click cancel, but in other scenarios I have values loaded from model. So after reopening dialog I want to have the same values as in model, not stored by Bean.

We have discussed some possible solutions in team, but for us, all seem to be nasty:

  1. We could clone selectedTerm on select and reload it from clone on cancel. It is nasty, because we need to implement clonable interface on each element we want to edit.
  2. We could write custom JavaScript to handle disabled events and other. But we want to avoid using JS, because this is not clean solution.
  3. We could reload selectedTerm from model on cancel and then replace it on terms list. But why are we forced to get something from DB again?
  4. We could reload whole terms list. This is even worse than 3rd solution.

We have also tried built-in reset options (resetInput tags and other), but no use. Is there any elegant way to fix this or maybe one of our suggestions is correct?

1 Answers
Related