Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No Update of Fields after Validation error

I have a primefaces dialog in which I can create or update an Employee. It will open by this

    </p:dialog><p:dialog id="employeeEditDialog" header="#{msg.employeeEdit}"
        widgetVar="dlgEmployeeEdit" resizable="false">

        <p:ajax  event="close" listener="#{employeeView.cancel}"
              update=":showEmployees:liste" />

        <ui:include src="/content/Employee/ShowEmployeeContent.xhtml" />
    </p:dialog>

And here is the Dialog Page

<h:form id="editContent">
<p:growl id="growl" showDetail="true" sticky="false" life="5000" />
<p:focus id="focusEdit" for="emSalutation" />
<h:panelGrid columns="2" id="contentGrid">
    <h:panelGrid columns="2" id="allgemein">                                                            <h:outputText value="#{msg.id}" />
        <h:outputText value="#{employeeView.newEmployee.id}" />

        <h:outputText value="#{msg.salutation}" />
        <p:selectOneMenu value="#{employeeView.newEmployee.salutation}"
            id="emSalutation">
            <f:selectItem itemLabel="" itemValue="" />
            <f:selectItems value="#{employeeView.salutations}" var="salutations"
                itemLabel="#{salutations.description}" itemValue="#{salutations}" />
        </p:selectOneMenu>

        <h:outputText value="#{msg.title}" />
        <p:inputText value="#{employeeView.newEmployee.title}" id="emTitle" />

        <h:outputText value="#{msg.name}" />
        <p:inputText value="#{employeeView.newEmployee.name}" id="emName"
            validatorMessage="#{msg.valName}" />

        <h:outputText value="#{msg.prename}" />
        <p:inputText value="#{employeeView.newEmployee.prename}"
            id="emPrename" />

        <h:outputText value="#{msg.loginname}" />
        <p:inputText value="#{employeeView.newEmployee.loginname}"
            validatorMessage="#{msg.valLogin}" />

        <h:outputText value="#{msg.department}" />
        <h:panelGrid columns="2" id="departmentGrid">
            <p:selectOneMenu value="#{employeeView.selectedDepartment.id}"
                id="emDepartment">
                <f:selectItem itemLabel="" itemValue="" />
                <f:selectItems value="#{employeeView.departmentList}"
                    var="department" itemLabel="#{department.description}"
                    itemValue="#{department.id}" />
            </p:selectOneMenu>
            <p:commandButton icon="ui-icon-disk" immediate="true"
                oncomplete="dlgDepartmentAdd.show()"
                update="departmentGrid, :departmentAddDialog">
            </p:commandButton>
        </h:panelGrid>

        <h:outputText value="#{msg.position}" />
        <h:panelGrid columns="2" id="positionGrid">
            <p:selectOneMenu value="#{employeeView.selectedPosition.id}"
                id="emPosition">
                <f:selectItem itemLabel="" itemValue="" />
                <f:selectItems value="#{employeeView.positionList}" var="position"
                    itemLabel="#{position.description}" itemValue="#{position.id}" />
            </p:selectOneMenu>
            <p:commandButton icon="ui-icon-disk" immediate="true" id="buttonPos"
                oncomplete="dlgPositionAdd.show()"
                update="positionGrid, :positionAddDialog">
            </p:commandButton>
        </h:panelGrid>

        <h:outputText value="#{msg.phone}" />
        <p:inputText value="#{employeeView.newEmployee.phone}" id="emPhone" />

        <h:outputText value="#{msg.fax}" />
        <p:inputText value="#{employeeView.newEmployee.fax}" id="emFax" />

        <h:outputText value="#{msg.email}" />
        <p:inputText value="#{employeeView.newEmployee.email}" id="emEmail"
            validator="myEmailValidator" validatorMessage="#{msg.valEmail}" />

        <h:outputText value="#{msg.employeedSince}" />
        <p:calendar value="#{employeeView.newEmployee.employeedSince}"
            id="emEmployeedSince" pattern="dd.MM.yyy" showOn="button" />

        <h:outputText value="#{msg.employeedEnd}" />
        <p:calendar value="#{employeeView.newEmployee.employeedEnd}"
            id="emEmployeedEnd" pattern="dd.MM.yyy" showOn="button" />

        <h:outputText value="#{msg.active}" />
        <p:selectBooleanCheckbox  value="#{employeeView.newEmployee.active}"
            id="emActive" /> 
    </h:panelGrid>

</h:panelGrid>

<h:panelGrid columns="3" class="buttonContent" id="button">
    <p:commandButton value="#{msg.save}" id="saveButton" update="growl"
        oncomplete="if ((!args.validationFailed)) dlgEmployeeEdit.hide()"
        actionListener="#{employeeView.saveOrUpdateEmployee}" />
    <p:commandButton value="#{msg.cancel}" immediate="true"
        oncomplete="dlgEmployeeEdit.hide()"/>
    <p:commandButton value="#{msg.delete}" immediate="true"
        oncomplete="dlgEmployeeDelete.show()"
        disabled="#{(employeeView.newEmployee.id == null) ? true : false}" />
</h:panelGrid>

<p:defaultCommand target="saveButton" /></h:form></html>

And now here are the two Methods which used in the Page:

/**
 * Methode zum Speichern und Updaten eines Mitarbeiters
 */
public void saveOrUpdateEmployee() {
    FacesContext context = FacesContext.getCurrentInstance();
    try {
        logger.debug("save aufgerufen " + this.newEmployee);
        if (this.selectedDepartment.getId() == null) {
            this.newEmployee.setDepartment(null);
        }
        else {
            this.newEmployee.setDepartment(this.departmentHandler.getDepartmentById(this.selectedDepartment.getId()));
        }
        if (this.selectedPosition.getId() == null) {
            this.newEmployee.setPosition(null);
        }
        else {
            this.newEmployee.setPosition(this.positionHandler.getPositionById(this.selectedPosition.getId()));
        }
        this.employeeController.saveOrUpdate(this.newEmployee);
        logger.info("Mitarbeiter erfolgreich gespeichert");
        context.addMessage(null, new FacesMessage("Successful", "Mitarbeiter gespeichert "));
    }
    catch (Exception e) {
        logger.error("Fehler beim Speichern des Mitarbeiters", e);
        context.addMessage(null, new FacesMessage("Fehler beim Speichern des Mitarbeiters", e.getMessage()));
    }
    this.loadPersons();
}

/**
 * Methode zum Abbrechen bei der Neuanlage/Änderung eines Mitarbeiters
 * Felder leeren
 */
public void cancel() {
    logger.debug("cancel()");
    this.newEmployee = new Employee();
    this.selected = new Employee();
    this.selectedDepartment = new Department();
    this.selectedPosition = new Position();
}

If now, validation failed, the dialog will not hide. This is OK and desired. It shows my created message via FacesMassages as required. If I then close the dialogbox by myself with the "cancel"-Button, dialog will close as expected. In the cancel()-method the object Employee will be set to a new instance of Employee (this.newEmployee = new Employee()) as you can see. But when I open the dialog after validation failure, the object "newEmployee" contains just the old values... Why does my method cancel()not work? I don't understand.

like image 686
Sandy Avatar asked Aug 02 '12 12:08

Sandy


1 Answers

This problem is related to JSF issue 1060 and in detail elaborated in this Q&A: How can I populate a text field using PrimeFaces AJAX after validation errors occur?

To the point, this behaviour is (unfortunately) correct as per current JSF specification and this can be solved as follows: during the invoke action phase you need to collect UIInput components which are included in the ajax render, but not in the ajax execute, and then invoke resetValue() method on them. This can be in a generic and reuseable fashion be done with help of OmniFaces ResetInputAjaxActionListener.

like image 131
BalusC Avatar answered Oct 23 '22 01:10

BalusC