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)?

Reply via email to