将EL表达式传递给复合组件

时间:2012-02-09 05:41:03

标签: jsf-2 el custom-component composite-component

我们仍处于JSF 1.2到2.0迁移场景中,我们现在面临与c表达式相关的问题:在EL表达式中使用的set或ui:param变量。

以下是事实。有一个按钮作为复合组件:

<cc:interface name="button" shortDescription="A button.">
    ...
    <cc:attribute
        name="disabled"
        required="false"
        default="false"
        shortDescription="The disabled flag." />
    ...
</cc:interface>

<cc:implementation>
    <ice:commandButton
        ...
        disabled="#{cc.attrs.disabled}"
        ... />
</cc:implementation>

现在我们尝试在工具栏中使用此按钮组件。使用c:set或ui:param(我们已经尝试过两种方式)在工具栏内确定按钮的禁用状态。

<c:set var="isButtonEnabled" value="#{backingBean.buttonEnabled}" />
or
<ui:param name="isButtonEnabled" value="#{backingBean.buttonEnabled}" />

#{isButtonEnabled}

<ctrl:button
    ...
    disabled="#{!isButtonEnabled}"
    ... />

所以这是我们的问题。如果我们简单地打印出&#34; isButtonEnabled&#34;的值。在工具栏中,它始终是正确的。所以支持bean是好的。但是当我们尝试将此值传递给复合组件时,它无法正常工作。 &#34;禁用&#34;始终被评估为false。

当然我们可以直接传递方法表达式(#{!backingBean.isButtonEnabled}),这样可以正常工作。但在我们的场景中,启用标志的确定要复杂得多,我只是尽量保持示例尽可能简单。此类标志用于工具栏内的多个按钮,因此我们希望通过使用c:set或ui:param来保持代码的可维护性。这是处理这个问题的错误方法吗?你推荐什么?

提前致谢。

SlimShady

1 个答案:

答案 0 :(得分:3)

您的问题是在JSF中完成值绑定的方式。首选方法是检索EL表达式,通过调用getValueExpression("attributeName")填充属性。然后,此EL表达式可用于获取或设置辅助bean中的值。由于您未将#{!isButtonEnabled}#{cc.attrs.disabled}传递给ice:commandButton,因此绑定失败。

我通过编写一个定义属性p:selectOneMenu的包UIComponent并将该属性传递给wrappedValue,为Primefaces的p:selectOneMenu组件解决了这个问题。在该属性的getter和setter中,我使用getValueExpression来恢复该属性的真实EL表达式。

<composite:interface componentType="de.gw2tome.component.valuewrapper">
    <composite:attribute name="value" type="de.gw2tome.models.Rarity"
        required="true" />
</composite:interface>

<composite:implementation>
    <p:selectOneMenu value="#{cc.wrappedValue}"/>
    ...
</composite:implementation>

@FacesComponent("de.gw2tome.component.valuewrapper")
public class ValueWrapper extends UINamingContainer {

    public void setWrappedValue(Object wrappedValue) {
        ValueExpression expr = getValueExpression("value");
        ELContext ctx = getFacesContext().getELContext();

        expr.setValue(ctx, wrappedValue);
    }

    public Object getWrappedValue() {
        ValueExpression expr = getValueExpression("value");
        ELContext ctx = getFacesContext().getELContext();

        return expr.getValue(ctx);
    }
}

现在可以通过以下方式使用该组件:

<g:rarityChooser value="#{itemSearchBean.minRarity}" />