Передача выражения EL в составной компонент - PullRequest
1 голос
/ 09 февраля 2012

мы все еще находимся в сценарии миграции 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» на панели инструментов, это всегда правильно. Так что с бобом все в порядке. Но когда мы пытаемся передать это значение составному компоненту, оно не работает. «Отключено» всегда оценивается как ложное.

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

Заранее спасибо.

SlimShady

1 Ответ

3 голосов
/ 29 июля 2012

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

Я решил это для p:selectOneMenu компонента Primefaces, написав обертку UIComponent, которая определяет свойство wrappedValue, и передал это свойство p:selectOneMenu. В получателе и установщике этого свойства я затем использовал 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}" />
...