【问题标题】:Can I tell JSF that an f:attribute applies to some part of my composite component?我可以告诉 JSF f:attribute 适用于我的复合组件的某些部分吗?
【发布时间】:2012-03-21 00:47:48
【问题描述】:

在下面的示例中,我能否以某种方式告诉 JSF <f:attribute> 适用于某些特定组件,就像我可以在 <f:convertNumber for="..."><f:validator for="..."> 中使用 for="..." 一样?

<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 之后,我使用了自定义验证器。为了给验证器提供一些参数,使用了&lt;f:attribute&gt;

接下来,当使用带有EditableValueHolder 的复合组件时,我可以(事实上:必须)将验证器分配给实际的h:inputText。但是我没有对f:attributes 做同样的事情,所以这些被添加到调用父组件中。例如:

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

...与&lt;f:validator for="myinput" ...&gt; 一起使用,如本文顶部所示,将验证器绑定到myparent:myinputtext,但属性绑定到myparent


解决方法:

documentation for &lt;f:attribute&gt; 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;
}

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

【问题讨论】:

    标签: java jsf-2 attributes composite-component


    【解决方案1】:

    这确实令人讨厌。 &lt;f:attribute&gt; 确实特定于最近的父 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>
    

    这样你问题中的第一个代码 sn-p 就可以工作了。

    至于您的最后一个代码 sn-p,更简单的是通过 UIComponent#getCompositeComponentParent() 获取复合组件父级。

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

    毕竟,我只会选择一个新的复合材料,如果需要的话,在&lt;ui:decorate&gt; 的帮助下使用与原始复合材料相同的模板。复合材料旨在最大限度地减少重复的样板。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-25
      • 1970-01-01
      • 2017-10-11
      • 2021-08-20
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多