2012-03-02 72 views
1

在下面的例子中,我能以某种方式告诉JSF <f:attribute>适用于某些特定组件,就像我可以在<f:convertNumber for="..."><f:validator for="...">中使用for="..."一样?我可以告诉JSF是一个f:属性适用于我的复合材料部件的某些部分?

<mytags:myCcInputWithValueHolder id="myparent" item="#{myBean.myDouble}" > 
    <f:convertNumber minFractionDigits="2" for="myinput"/> 
    <f:validator validatorId="bindableDoubleRangeValidator" for="myinput"/> 
    <f:attribute name="minimum" value="#{30.00}"/> 
    <f:attribute name="maximum" value="#{39.99}"/> 
</mytags:myCcInputWithValueHolder> 


背景:

BalusC's solution to a JSF issue,我用一个自定义的验证。为了给该验证器提供一些参数,使用<f:attribute>

接着,使用复合部件与EditableValueHolder时,我可以(实际上:必须)验证分配给实际h:inputText。但我没有这样做的f:attribute S也是一样的,所以这些被添加到调用父组件代替。例如:

<composite:attribute name="item" .../> 
<composite:editableValueHolder name="myinput" targets="myinputtext"/>   
: 
<h:inputText id="myinputtext" value="#{cc.attrs.item}"> 
    <!-- <composite:insertChildren /> doesn't change anything --> 
</h:inputText> 

...这篇文章上的顶部,如图与<f:validator for="myinput" ...>使用的,结合验证器myparent:myinputtext,但属性绑定到myparent


解决方法:

documentation for <f:attribute> indeed states

添加属性与最接近的父UIComponent自定义操作相关的UIComponent。

而且考虑到,下面的复合物成分也按预期工作:

<composite:attribute name="item" .../> 
<composite:attribute name="min" .../> 
<composite:attribute name="max" .../> 
: 
<h:inputText id="myinput" value="#{cc.attrs.item}"> 
    <f:convertNumber minFractionDigits="2"/> 
    <f:validator validatorId="bindableDoubleRangeValidator"/> 
    <f:attribute name="minimum" value="#{cc.attrs.min}"/> 
    <f:attribute name="maximum" value="#{cc.attrs.max}"/> 
</h:inputText> 

...有:

<mytags:myCcInputWithValidator 
    item="#{myBean.myDouble}" min="#{30.00}" max="#{39.99}"/> 

另外,我可以轻松地扩展BalusC's BindableDoubleRangeValidator递归到父组件获得值:

Object getAttribute(FacesContext c, UIComponent component, String name) { 
    Object result = component.getAttributes().get(name); 
    if (result == null && component.getParent() != null) { 
     result = getAttribute(c, component.getParent(), name); 
    } 
    return result; 
} 

仍然:有更好的解决方案吗?

回答

3

这的确是讨厌。该<f:attribute>确实是具体到最近的父UIComponent。如果您将它嵌套在复合材料中,那么它将特定于复合材料部件本身。一种方法是将复合材料中的属性复制到有问题的输入组件中:

<h:inputText id="myinputtext" value="#{cc.attrs.item}"> 
    <f:attribute name="minimum" value="#{cc.attrs.minimum}"/> 
    <f:attribute name="maximum" value="#{cc.attrs.maximum}"/> 
</h:inputText> 

以便您的问题中的第一个代码段可以工作。

至于你最后的代码片断,简单的将是UIComponent#getCompositeComponentParent()得到复合材料部件父来代替。

Object getCompositeParentAttribute(UIComponent component, String name) { 
    UIComponent composite = UIComponent.getCompositeComponentParent(component); 
    return composite.getAttributes().get(name); 
} 

毕竟,我只是选择了一个新的复合材料,必要时使用相同的模板,因为原来的复合材料的<ui:decorate>帮助。复合材料旨在最大限度地减少重复的样板。

<my:inputDouble value="..." min="..." max="..." /> 

<cc:implementation> 
    <ui:decorate template="/WEB-INF/templates/someCommonTemplate.xhtml"> 
     <ui:define name="input"> 
      <h:inputText id="myinput" value="#{cc.attrs.value}"> 
       <f:convertNumber minFractionDigits="2" /> 
       <f:validator validatorId="bindableDoubleRangeValidator"/> 
       <f:attribute name="minimum" value="#{cc.attrs.min}"/> 
       <f:attribute name="maximum" value="#{cc.attrs.max}"/> 
      </h:inputText> 
     </ui:define> 
    </ui:decorate> 
</cc:implementation> 
+0

(而与此同时测试以及:完美的作品。) – Arjan 2012-03-05 17:43:36

+0

不客气。 – BalusC 2012-03-05 17:49:07

相关问题