myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Yee CN <ye...@streamyx.com>
Subject RE: Retrieving component values in validation methods
Date Wed, 14 Dec 2005 07:01:18 GMT
Yes - please share your findings. This is one 'burning' problem that is high
in my list of things to investigate.

Maybe myfaces should implement a compareValidator tag - something like:

<t:compareValidator 
	ControlToValidate="clientId1" ControlToCompare="clientId2"
    	Operator="Equals"
    	ErrorMessage="* You must enter the same values into textbox 1 and
textbox 2"
/>

Or maybe JSF should provide a validator interface that accepts an arbitrary
number of values?

<f:crossValidator values="clientId1, clientId2, clientId3..." />

public void crossValidate(
	FacesContext context, List<UIComponent,Object> values); 


Regards,
Yee

-----Original Message-----
From: Simon Kitching [mailto:skitching@obsidium.com] 
Sent: Wednesday, 14 December 2005 7:46 AM
To: MyFaces Discussion
Subject: Re: Retrieving component values in validation methods

Matthias Kahlau wrote:
> Hi!
> 
> 
> Some questions regarding validator methods (using "validator "attribute of
> components):
> 
> 1) In which phase are these methods invoked? Always in process validations
> or dependent on immediate setting?

In the "decode" part of the "apply-values" phase when the component is 
immediate.

In "validate" phase otherwise.

> 
> 2) Which is the right method to get the values of other components in the
> validator method, getSubmittedValue(), getLocalValue(), dependent on
> configuration issues (immediate) of the component owning the validator and
> other components asked in the validator method?

Hmm. You're trying to implement "cross-component" validation I presume?

I've not tried to do this myself, but as I have spent some time recently 
getting familiar with the validation process here's what I think will 
happen....


When the validator's component has immediate=false:
===================================================
All other components will have performed "decode", ie set their 
submittedValue from the input request params.

Components occurring *before* the component associated with the 
validator which have *valid* input will have converted the data, stored 
it in localValue, then run the validators. Such components will 
therefore have localValue set, and submittedValue=null. Their "isValid" 
method will return true.

Components occurring *before* the component associated with the 
validator whose *convert* operation failed will have the "new" value 
left in submittedValue. But in this case, you'll probably not be able to 
do your cross-component validation anyway, as all that's available to 
you is the raw unconverted submittedValue. Such components will have 
isValid return false.

Components occurring *before* the component associated with the 
validator whose *convert* operation succeeded but validate failed will 
have the "new" value left in localValue. But in this case, you'll 
probably not want to do your cross-component validation anyway, as the 
component is already known to be invalid. Such components will have 
isValid return false.

Components occurring *after* the component associated with the validator 
but which are not immediate will have set their submittedValue but not 
tried to convert/validate. Therefore only the submittedValue is 
available. And unfortunately isValid will return true.

Components that are declared "immediate" will have already performed 
decode, convert, validate. So they act just like components occurring 
"before" the validator's component, regardless of where they actually 
occur in the page.

I would therefore suggest:
(a) always put your cross-component validator on the last component 
involved in the check
(b) check for other.submittedValue != null  ==> don't bother validating, 
as the input value couldn't be converted
(c) check for !other.isValid ==> don't bother validating, as the
component is already invalid.

When the validator's component has immediate=false:
====================
The validate call will occur before other components have even tried to 
decode their values from the http request. Cross-component validation is 
therefore quite impossible at this time, unless validating against 
components which are both earlier in the page *and* themselves immediate.


See also:
   http://www.jsf-faq.com/faqs/faces-validation.html#133


There doesn't seem to be a good FAQ entry anywhere on implementing 
cross-component validation, so maybe if you get this working it would be 
a good idea to create a wiki HOWTO entry?

Cheers,

Simon


Mime
View raw message