2012-03-02 48 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

相關問題