Okay, I was too impatient to wait for a reply. I wouldn't mind to know
if anyone has a better approach, but I just got this to work by:
<label>
<t:selectBooleanCheckbox
id="myCheckbox"
value="#{bean.filter}" />
Search for value:
</label>
<t:inputText
required="#{bean.filter}"
value="#{bean.filterValue}">
<my:required compareTo="myCheckbox" value="#{true}" />
</t:inputText>
Where the required code is:
public class UIRequired
extends UIComponentBase
{
private final static String COMPONENT_FAMILY = "mypackage.Validation";
public final static String COMPONENT_TYPE = "mypackage.Required";
private String compareTo;
private Object value;
private String _for;
/**
* @return the value
*/
public Object getValue()
{
if (this.value != null) return this.value;
ValueBinding vb = getValueBinding("value");
return (vb == null) ? null : (Object)vb.getValue(getFacesContext());
}
/**
* @param value the value to set
*/
public void setValue(Object value)
{
this.value = value;
}
/**
* @return the for
*/
public String getFor()
{
if (this._for != null) return this._for;
ValueBinding vb = getValueBinding("_for");
return (vb == null) ? null : (String)vb.getValue(getFacesContext());
}
/**
* @param forVal the for to set
*/
public void setFor(String forVal)
{
this._for = forVal;
}
/**
* @return the compareTo
*/
public String getCompareTo()
{
if (this.compareTo != null) return this.compareTo;
ValueBinding vb = getValueBinding("compareTo");
return (vb == null) ? null : (String)vb.getValue(getFacesContext());
}
/**
* @param compareTo the compareTo to set
*/
public void setCompareTo(String compareTo)
{
this.compareTo = compareTo;
}
/**
* @see javax.faces.component.UIComponent#getFamily()
*/
@Override
public String getFamily()
{
return COMPONENT_FAMILY;
}
/**
* @see javax.faces.component.UIComponentBase#getRendererType()
*/
@Override
public String getRendererType()
{
return null;
}
/**
* @see
javax.faces.component.UIComponentBase#saveState(javax.faces.context.FacesContext)
*/
@Override
public Object saveState(FacesContext context)
{
return new Object[] {
super.saveState(context),
_for,
compareTo,
value,
};
}
/**
* @see
javax.faces.component.UIComponentBase#restoreState(javax.faces.context.FacesContext,
java.lang.Object)
*/
@Override
public void restoreState(FacesContext context, Object state)
{
Object[] arr = (Object[])state;
int index = -1;
super.restoreState(context, arr[++index]);
this._for = (String)arr[++index];
this.compareTo = (String)arr[++index];
this.value = arr[++index];
}
/**
* @see
javax.faces.component.UIComponentBase#processValidators(javax.faces.context.FacesContext)
*/
@Override
public void processValidators(FacesContext context)
{
super.processValidators(context);
String forVal = getFor();
UIInput input = null;
if (forVal != null)
input = (UIInput)this.findComponent(forVal);
if (input == null)
{
for (UIComponent comp = this; comp != null; comp = comp.getParent())
{
if (comp instanceof UIInput)
{
input = (UIInput)comp;
break;
}
}
}
UIInput compareToInput = (UIInput)this.findComponent(getCompareTo());
Object value = (compareToInput.isLocalValueSet()) ?
compareToInput.getLocalValue() : compareToInput.getValue();
input.setRequired(ObjectUtils.equals(value, getValue()));
}
}
BTW the "ObjectUtils.equals" method is just a handy method I use to
compare to values that may be null. If neither are null it uses the
equals method to compare.
On 3/2/07, Andrew Robinson <[EMAIL PROTECTED]> wrote:
I have ideas on how to handle this situation, but none seem very
elegant. What I have is a filter dialog for our application. The UI
has options where the user chooses if they want to filter by
something, and then they can type in the value. A simplistic
representation:
<label>
<t:selectBooleanCheckbox
value="#{bean.filter}" />
Search for value:
</label>
<t:inputText
required="#{bean.filter}"
value="#{bean.filterValue}" />
Now most sound notice the problem immediately, the required of the
inputText will be evaluated against the bean's value which at
validation time has not been updated yet, the value that I really
want to compare is the submitted value of the checkbox.
Marking the checkbox as immediate does not help, as that just changes
when validation takes place in UIInput, not when the update is
processed. There is no easy way I know of in JSF to have the required
based on the state of the checkbox.
Anyone know of a good solution for this without performing the
validation in the INVOKE_APPLICATION phase (in the action or
actionListener)?