Передача выражения EL в составной компонент

мы все еще находимся в сценарии миграции JSF с 1,2 до 2.0, и теперь мы сталкиваемся с проблемой, связанной с переменными c: set или ui: param, используемыми внутри выражения EL.

Вот факты. В качестве составного компонента есть кнопка:

<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}"
    ... />

Итак, вот наша проблема. Если мы просто напечатаем значение "isButtonEnabled" на панели инструментов, это всегда правильно. Таким образом, поддержка bean в порядке. Но когда мы пытаемся передать это значение составному компоненту, он не работает. "Отключено" всегда оценивается как false.

Конечно, мы можем передать выражение метода напрямую (# {! backingBean.isButtonEnabled}), и это будет работать нормально. Но в нашем сценарии определение включенного флага намного сложнее, и я просто попытался максимально упростить пример. Кроме того, этот флаг используется для нескольких кнопок внутри панели инструментов, поэтому мы хотели сохранить поддерживаемый код с помощью c: set или ui: param. Это неправильный способ справиться с этим? Что вы рекомендуете?

Спасибо заранее.

SlimShady

Ответ 1

Ваша проблема заключается в том, как привязка стоимости выполняется в JSF. Предпочтительным способом является получение выражения EL, для которого атрибут был заполнен вызовом getValueExpression("attributeName"). Затем это выражение EL можно использовать для получения или установки значения в базе bean. Поскольку ваш не проходящий #{!isButtonEnabled}, но #{cc.attrs.disabled} до ice:commandButton, сбой не выполняется.

Я решил это для компонента p:selectOneMenu в Primefaces, написав wrapping UIComponent, который определяет свойство wrappedValue и передал это свойство в 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}" />