Primefaces JSF update after validation failed doesn't work

旧时模样 提交于 2019-12-04 16:30:18

问题


I have a problem with the validation of a <p:inputText> and updating its content.

Basically when the inputText validation fails, it never gets updated again.

Here's a simple example to clarify:

The Facelet:

!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">
    <h:head>
    </h:head>
    <body>
    <h1>Test</h1>

        <h:form id="list" prependId="false">
            <ul>
                <li>Element 1&#160;
                    <p:commandLink action="#{Test.assignElement}" update="detail_value">
                        <f:setPropertyActionListener target="#{Test.currentElement}" value="1" />
                        Assign
                    </p:commandLink>
                </li>
                <li>Element 2&#160;
                    <p:commandLink action="#{Test.assignElement}" update="detail_value">
                        <f:setPropertyActionListener target="#{Test.currentElement}" value="2" />
                        Assign
                    </p:commandLink>
                </li>
            </ul>
        </h:form>

        <h:form id="detail" prependId="false">
            <p:inputText value="#{Test.element}" id="detail_value" required="true" styleClass="#{Faces.messagesFor['detail_value'] ? 'border:1px solid red' : ''}">
                <p:ajax event="blur" update="detail_value"></p:ajax>
            </p:inputText>
        </h:form>
    </body>
</html>

The Test bean:

package com.easydevel.test;

public class Test {

    private String currentElement;
    private String element;

    public String getCurrentElement() {
        return currentElement;
    }

    public void setCurrentElement(String currentElement) {
        this.currentElement = currentElement;
    }

    public String getElement() {
        return element;
    }

    public void setElement(String element) {
        this.element = element;
    }

    public String assignElement(){
        setElement(getCurrentElement());
        return "";
    }

}

If you click on the commandLinks below the "Element"s the input field gets updated, but when a validation fails (simply leave the input text blank, and click on any other part of the page), the border of the input turns red. After that it never gets updated again when clicking on the above mentioned commandLinks.

Any ideas?


回答1:


Arjan tijms answer will works, however the best solutions I found are:

  1. Use Omnifaces Solution So, instead of implementing the listener your self all what you need is just one line of simple code.

    <h:commandButton value="Update" action="#{bean.updateOtherInputs}">
    <f:ajax execute="currentInputs" render="otherInputs" />
    <f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" />
    </h:commandButton>
    
  2. If you are using Primefaces you can use resetInput component:

    <p:commandButton value="Reset Non-Ajax" actionListener="#{resetInputView.reset}"
    immediate="true" ajax="false" style="margin-right:20px;">
    <p:resetInput target="panel" />
    </p:commandButton>  
    



回答2:


This is the notorious case of 'input elements' (EditableValueHolders actually) that once validation has failed for them can never be updated again via AJAX re-rendering.

See:

  1. JSF AJAX validation: execute="@this" render="@form" inconsistent depending on prior requests
  2. How can I populate a text field using PrimeFaces AJAX after validation errors occur?
  3. http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1060

A work-around is to create an action listener that resets the components that are to be re-rendered. See the last page of this: http://community.jboss.org/message/620000

If this behavior bothers you (I guess it does), then please don't hesitate to vote for JAVASERVERFACES_SPEC_PUBLIC-1060 and if possible leave a comment telling what you expected and why.




回答3:


I will answer myself.

Based on the links provided by Arjan, i develop the actionListener to clean the form elements. and It works.

THE FACELET:

<p:commandLink action="#{Test.assignElement}" update="detail_value">
                       <f:actionListener type="com.easydevel.utils.CleanForms" />
                       <f:setPropertyActionListener target="#{Test.currentElement}" value="1" />
                       Assign
</p:commandLink>    

And the LISTENER....

package com.easydevel.utils;

import java.util.Collection;
import java.util.Iterator;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.PartialViewContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;


public class CleanForms implements ActionListener {

 public void processAction(ActionEvent event) throws AbortProcessingException {                
     FacesContext facesContext = FacesContext.getCurrentInstance();
     PartialViewContext ajaxContext = facesContext.getPartialViewContext();
     UIComponent root = facesContext.getViewRoot();          
     Collection<String> renderIds = ajaxContext.getRenderIds();
     for (String renderId : renderIds) {
        UIComponent form = findComponent(root,renderId);
        if (form != null) {
             clearComponentHierarchy(form);
        }
     }
 }

 private void clearComponentHierarchy(UIComponent pComponent) {

      if (pComponent.isRendered()) {

           if (pComponent instanceof EditableValueHolder) {
                EditableValueHolder editableValueHolder = (EditableValueHolder) pComponent;
                editableValueHolder.setSubmittedValue(null);
                editableValueHolder.setValue(null);
                editableValueHolder.setLocalValueSet(false);
                editableValueHolder.setValid(true);
           }          

           for (Iterator<UIComponent> iterator = pComponent.getFacetsAndChildren(); iterator.hasNext();) {
                clearComponentHierarchy(iterator.next());
           }          

      }
 }

 private static UIComponent findComponent(UIComponent base, String id) {
       if (id.equals(base.getId()))
         return base;
       UIComponent kid = null;
       UIComponent result = null;
       Iterator kids = base.getFacetsAndChildren();
       while (kids.hasNext() && (result == null)) {
         kid = (UIComponent) kids.next();
         if (id.equals(kid.getId())) {
           result = kid;
           break;
         }
         result = findComponent(kid, id);
         if (result != null) {
           break;
         }
       }
       return result;
   }

}


来源:https://stackoverflow.com/questions/8677985/primefaces-jsf-update-after-validation-failed-doesnt-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!