2012-03-02 5 views
1

<f:convertNumber for="..."><f:validator for="...">for="..."を使用できるのと同様に、次の例では、<f:attribute>が特定のコンポーネントに適用されることをJSFに何とか伝えることができますか?f:属性が複合コンポーネントの一部に適用されることをJSFに伝えることはできますか?

<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のために同じことをしないので、これらは代わりに呼び出し元の親コンポーネントに追加されます。たとえば:

<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()で取得する方が簡単です。 <ui:decorate>の助けを借りて、元の複合と同じテンプレートを使用して、必要に応じて

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

すべての後、私はちょうど、新しい複合を選ぶと思います。複合材は、繰り返される定型文を最小限に抑えるためのものです。

<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

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

は(そしてその間にもテスト:完璧に動作します。) – Arjan

+0

どういたしまして。 – BalusC

関連する問題