Fórum

weird behaviour of UIComponent-children in JSF Validator

thumbnail
Johann Kneringer, modificado 11 Anos atrás.

weird behaviour of UIComponent-children in JSF Validator

Junior Member Postagens: 42 Data de Entrada: 10/11/11 Postagens Recentes
Hey there.

I have a Validator for required Fields which looks like this:

package mypackage;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlGraphicImage;
import javax.faces.context.FacesContext;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

import com.liferay.faces.portal.el.I18N;
@FacesValidator("validateEmptyFields")
public class RequiredFieldValidator implements Validator {

	@Override
	public void validate(FacesContext context, UIComponent component, Object obj) throws ValidatorException {
		
		String family = component.getFamily();
		String componentWarningId = component.getId()+"warning";
		if(obj==null || obj.toString().equals(""))
		{
			//Falls schon ein Warning Symbol vorhanden ist, muss dieses vorher gelöscht werden
			if(component.getChildren().size()!=0)
			{	
				component.getChildren().clear();
			}
			
			if(family.equals("javax.faces.Input"))
			{
				component.getAttributes().put("styleClass", "componentErrorStyle");
			}
			else if(family.equals("javax.faces.SelectOne"))
			{
				component.getAttributes().put("styleClass", "comboboxErrorStyle");
			}
			
			I18N i18n = new I18N();
			
			HtmlGraphicImage img = new HtmlGraphicImage();
			img.setValue("/resources/images/warning.png");
			img.setId(componentWarningId);
			img.setHeight("16");
			img.setTitle(i18n.getString("required"));
								
			UIComponent warningComponent = (UIComponent)img;
			
			component.getChildren().add(warningComponent);
			
			throw new ValidatorException(new FacesMessage());
		}
		else
		{
			UIComponent warningComponent =	component.findComponent(componentWarningId);
			
			//Wenn Input-Text, dann können alle Kinder gelöscht werden
			if(family.equals("javax.faces.Input"))
			{
				component.getAttributes().put("styleClass", "textBoxes");
			}
			//Wenn SelectOne (Menu),dann nicht, da ansonsten die einzelnen SelectItems gelöscht werden
			else if(family.equals("javax.faces.SelectOne"))
			{
				component.getAttributes().put("styleClass", "comboBoxes");
			}
			
			if(warningComponent!=null)
			{
				component.getChildren().remove(warningComponent);
			}
		}
	}
}


The validator is called in Icefaces component using the validator="validateEmptyFields" tag. Some components have partialSubmit="true".

If a field is empty, the styleclass of the component is changed and a warning image is added to the components children...This part works perfect...

The weird behaviour is in the second part, when there is already a warning image of the first validation, and this image has to be removed because there is a value in the component...

The funny thing here is, that the Styleclass-change of the component works perfect, but the image is not getting removed of the children...If I do debug this method, I see, that the image gets deleted from the components children, but on my webpage only the styleclass is getting changed, the image is still being displayed...

I am a little bit confused at this point...Do you have some suggestions?

best regards,
Johann
thumbnail
Neil Griffin, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
The typical way of handling this is to simply have the validator throw the exception with a meaningful FacesMessage, and not perform any manipulation of attributes or of the JSF view's component tree.

The JSF API already has a javax.faces.validator.RequiredValidator that does this with FacesMessage that is set with FacesMessage.SEVERITY_ERROR.

The h:message and h:messages component tags have attributes for handing SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR, and SEVERITY_FATAL. For example:

<h:message infoClass="portlet-msg-info" warnClass="portlet-msg-warn" errorClass="portlet-msg-error" fatalClass="portlet-msg-error" />


Liferay Faces Bridge will automatically set these for you according to the standard Portlet 2.0 CSS classes. There's nothing for you to do as a JSF portlet developer to take advantage of this.

Additionally, the Liferay Portal CSS will automatically style the h:message or h:messages rendered markup with images and text. Recommend that you look at portal-web/docroot/html/themes/_styled/css/portlet.css in the Liferay Portal source code, or in one of your Liferay Portal themes.
thumbnail
Johann Kneringer, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Junior Member Postagens: 42 Data de Entrada: 10/11/11 Postagens Recentes
Hey Neil,

thanks for your reply...

I know that there is a validation implemented for required fields...But i want to make a custom validation, because i want to style the component in a custom way...

If I use the h:message tag, my form gets spread, if there is an error occuring...But I dont want this...

What I want is to update the css style class of the component where the error occurs. I want to give a red border around this component. This is already working...

Additional to this I want to display an image next to the component with the error message in the title, so that the user sees that there is an error and by focusing the image the user will see the error message, because its written in the title...I am able to add an image, but as written above, I'm not able to remove the graphic component, when there is no error in it...


Is there maybe another way to use the required implementation in jsf and just override the output-styling or displaymethod?
thumbnail
Neil Griffin, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
I would recommend that you develop a thread-safe PhaseListener that listens to the PROCESS_VALIDATIONS phase of the JSF lifecycle. In the afterPhase(PhaseEvent) method, you could recurse through the component tree (starting at UIViewRoot) and simply append a CSS class name like "error-highlight" to all instances of EditableValueHolder where the isValid() method returns false.

Rather than dynamically adding an image component to the component tree, I think all of the styling should be done by CSS. For example, Liferay's portlet.css displays an image/icon within the error message like this:
.portlet-msg-error {
	background-color: #FDD;
	background-image: url(../images/messages/error.png);
	border-color: #F00;
}
thumbnail
Johann Kneringer, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Junior Member Postagens: 42 Data de Entrada: 10/11/11 Postagens Recentes
Neil Griffin:
I would recommend that you develop a thread-safe PhaseListener that listens to the PROCESS_VALIDATIONS phase of the JSF lifecycle. In the afterPhase(PhaseEvent) method, you could recurse through the component tree (starting at UIViewRoot) and simply append a CSS class name like "error-highlight" to all instances of EditableValueHolder where the isValid() method returns false.

Rather than dynamically adding an image component to the component tree, I think all of the styling should be done by CSS. For example, Liferay's portlet.css displays an image/icon within the error message like this:
.portlet-msg-error {
	background-color: #FDD;
	background-image: url(../images/messages/error.png);
	border-color: #F00;
}



thanks a lot Neil...Got it implemented with your instructions ;-)
thumbnail
Neil Griffin, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
That's great news -- so glad to hear that it's working for you. emoticon
thumbnail
Neil Griffin, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Liferay Legend Postagens: 2655 Data de Entrada: 27/07/05 Postagens Recentes
News: Looks like the new OmniFaces project has support for highlighting fields that failed validation. I haven't tried it with Liferay Faces but it looks like it has promise.
thumbnail
Johann Kneringer, modificado 11 Anos atrás.

RE: weird behaviour of UIComponent-children in JSF Validator

Junior Member Postagens: 42 Data de Entrada: 10/11/11 Postagens Recentes
thanks for pointing that out neil. Maybe I'll give that a try in my next project...