JSF-выражение для оценки тегов атрибутов - PullRequest
1 голос
/ 02 марта 2012

У меня проблема с оценкой выражений EL, содержащих var s, созданных другими тегами.

У меня есть проект, в котором я использую пользовательский валидатор.

public class MyValidator implements Validator, StateHolder

У меня есть связанный с ним класс тегов:

public class MyValidatorTag extends ValidatorTag

этот класс допускает атрибут fieldName с соответствующим файлом tld для тега:

<tag>
    <name>my-validator</name>
    <tag-class>my.packaga.MyValidatorTag</tag-class>
    <body-content>JSP</body-content>
    <description>This is my validator</description>
    <attribute>
        <name>fieldName</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
        <type>java.lang.String</type>
        <description>This is some field I need</description>
    </attribute>
</tag>

Пока все хорошо.Но эта настройка не позволяет использовать выражения JSF EL для значения атрибута.Итак, класс валидатора (не класс тега) Я использую этот код для оценки значения атрибута:

public static String evaluateEl(String expression) {
    String value = null;
    if (expression == null) {
        return "";
    }
    if ((expression.indexOf("#{") != -1)
        && (expression.indexOf("#{") < expression.indexOf('}'))) {
        Object evaledValue =
            FacesContext.getCurrentInstance().getApplication().createValueBinding(
                expression).getValue(FacesContext.getCurrentInstance());
        if (evaledValue != null) {
            value = evaledValue.toString();
        } else {
            value = null;
        }
    } else {
        value = expression;
    }
    return value;
}

Он ограничен строками и работает для большинства выражений EL.Выражение Hello #{1 eq 2} приведет к тому, что атрибут будет иметь значение Hello false.Но есть случай, для которого это не сработает.Любое выражение, которое содержит var, созданное другим тегом, не работает.Таблицы данных, итераторы данных и, в частности, <f:loadBundle>, например,

<f:loadBundle basename="mypackage.message.ui-strings" var="msgs" />

За ним следует компонент ввода, содержащий валидатор:

<cust:my-validator fieldName="#{msgs['myfield1.name']}"></cust:my-validator>

Имя полявычисляет пустую строку, используя приведенный выше код оценки выражения.Изменение на #{requestScope.msgs.... не решает проблему.Рассматривая реализацию loadBundle, он добавляет var msgs к запросу scope, поэтому я не понимаю, почему vars не работают для меня.Пожалуйста, кто-нибудь, помогите мне понять.

1 Ответ

4 голосов
/ 02 марта 2012

Любое выражение, которое содержит переменную, созданную другим тегом, не работает. Datatables, dataiterators и прежде всего, например,

Обработчики тегов, такие как <f:xxx>, <c:xxx> и некоторые <ui:xxx> (те , а не с атрибутом rendered), выполняются во время построения представления JSF, когда должно быть дерево компонентов пользовательского интерфейса JSF. производится. Они не являются частью дерева компонентов пользовательского интерфейса. Они уже выполнили свою работу по производству необходимых компонентов пользовательского интерфейса JSF.

Компоненты пользовательского интерфейса, такие как <h:xxx> и некоторые <ui:xxx> (те, которые имеют атрибут rendered), выполняются во время визуализации представления JSF, когда должна быть создана большая строка HTML, которая должна быть отправлена ​​в ответ HTTP от текущий HTTP-запрос.

Так что они не работают синхронно.

Для конечного пользователя валидатора есть несколько способов обойти это, все перечислены в этом ответе: Как установить свойства конвертера для каждой строки таблицы данных?

Для разработчика есть другое решение: пусть вместо этого валидатор расширяет UIComponentBase и выполняет задание в processValidators(). Родительский компонент просто доступен по UIComponent#getParent(), а его отправленное значение в свою очередь доступно по UIInput#getSubmittedValue().

...