Как получить значение компонента JSF с помощью EL? - PullRequest
8 голосов
/ 21 декабря 2009

Прежде чем продолжить, посмотрите этот вопрос

Форма JSF снова отображается следующим образом:

<f:view>
    <h:form>
        <div>
            <label>Id</label>
            <input type="text" name="accountId"/>
        </div>
        <div>
            <label>Amount</label>
            <input type="text" name="amount"/>
        </div>
        <h:commandButton value="Withdraw" action="#{accountService.withdraw(param.accountId, param.amount)}"/>
    </h:form>
</f:view>

Обратите внимание, что я использовал <input type="text" name="amount"> вместо <h:inputText id="amount">. Чтобы получить его значение с помощью распознавателя Seam EL, я использую param.amount.

Бывает, что если я использую <input type="text" и что-то идет не так на стороне сервера, мне нужно снова показать страницу. Таким образом, его переданное значение не извлекается , потому что это обычный HTML-код. Из-за этого мне нужно использовать компонент <h:inputText JSF.

Итак, вопрос: как получить значение <h:inputText компонента JSF с помощью языка выражений ?

Ответы [ 3 ]

18 голосов
/ 21 декабря 2009

Идентификаторам клиента JSF предшествует идентификатор клиента родительских UINamingContainer компонентов (например, h:form, h:dataTable, f:subview). Если вы проверите сгенерированный источник HTML в своем веб-браузере (щелкните правой кнопкой мыши, просмотрите исходный код), то вы должны увидеть их. id и name сгенерированных элементов ввода предваряются id родительской формы. Вам нужно использовать то же имя, что и ключ в карте параметров. Поскольку символ-разделитель, двоеточие :, является недопустимым символом в EL, для их извлечения необходимо использовать фигурную скобку param['foo:bar'].

<f:view>
    <h:form id="account">
        <div>
            <label>Id</label>
            <h:inputText id="id" />
        </div>
        <div>
            <label>Amount</label>
            <h:inputText id="amount" />
        </div>
        <h:commandButton value="Withdraw" 
            action="#{accountService.withdraw(param['account:id'], param['account:amount'])}"/>
    </h:form>
</f:view>

Без параметров метода, подобного Seam-EL (вы, очевидно, не хотите / не имеете его), вы также можете получить к ним доступ в карте параметров запроса, используя идентификаторы клиента в качестве ключей:

public void withDraw() {
    Map<String, String> map = FacesContext.getCurrentInstance().getRequestParameterMap();
    String id = map.get("account:id");
    String amount = map.get("account:amount");
    // ...
}

Нет необходимости говорить, что это противно. Просто сделайте это обычным способом JSF, свяжите значения со свойствами bean.

Редактировать: согласно последнему отредактированному вопросу:

Таким образом, вопрос заключается в следующем: как извлечь значение компонента <h:inputText JSF с помощью языка выражений?

На это уже отвечали раньше. Используйте имя , сгенерированное JSF , в качестве имени параметра. Обычно это шаблон formId:inputId, где formId - это id родительского компонента UIForm, а inputId - это id компонента UIInput. Проверьте сгенерированный вывод HTML на точное имя сгенерированного поля <input type="text">. Чтобы получить значение параметра, используйте скобку ['name'], потому что нельзя использовать двоеточие : в EL, как в ${param.formId:inputId}.

Таким образом:

#{param['formId:inputId']}
1 голос
/ 21 декабря 2009

Имена / идентификаторы параметров для inputText инкапсулированы средством визуализации управления и, в конечном счете, являются деталями реализации. На практике они используют clientId. Там не должно быть необходимости читать их непосредственно из карты параметров; используйте привязку значений, чтобы вставить их в модель и прочитать их оттуда.

Вы можете считывать значения непосредственно из компонента, используя EL, связывая компонент с управляемым компонентом. Для простоты вот один из них, связанный с областью запроса:

<!-- bind a UIComponent to the request map as "foo" -->
<h:inputText binding="#{requestScope.foo}" />
<!-- read value from a UIComponent that implements ValueHolder -->
#{requestScope.foo.value}

Но, как правило, в этом нет никакого преимущества перед:

<!-- bind a value to the request map as "foo" -->
<h:inputText value="#{requestScope.foo}" />
<!-- read value from the request scope -->
#{requestScope.foo}

Чтобы не загрязнять карту запроса (что может привести к коллизиям между представлениями), используйте управляемый компонент для именования / инкапсуляции ваших значений вместо непосредственного использования области запроса.

0 голосов
/ 27 декабря 2009

Хотя я могу получить значение компонента JSF через его идентификатор клиента, есть некоторые недостатки:

  1. Согласно ответу Макдауэлла, идентификатор клиента является подробностью реализации
  2. Идентификатор клиента может отличаться от идентификатора компонента, если в иерархии элементов управления имеется более одного контейнера именования. (JSF в книге действий)

Поэтому, если вы не хотите полагаться на идентификатор клиента, вы можете реализовать свой собственный ElResolver следующим образом:

public class ComponentIdResolver extends ELResolver {

    public Object getValue(ELContext context, Object base, Object property) {
        if (base instanceof UIComponent && property instanceof String) {
            UIComponent r = ((UIComponent) base).findComponent((String) property);

            if (r != null) {
                context.setPropertyResolved(true);

                return r;
            }
        }

        return null;
    }

}

Теперь я могу использовать что-то вроде (Уведомление о способе вывода)

<h:inputText id="accountId" />
<h:inputText id="amount" />
<h:commandButton value="Withdraw" action="#{accountService.withdraw(view.accountId.value, view.amount.value)}"/>

Представление является неявным объектом JSF (аналогично FacesContext.getCurrentInstance (). GetViewRoot ())

Затем зарегистрируйте свой ELResolver, как показано ниже (face-config.xml)

<application>
    <el-resolver>br.com.view.resolver.ComponentIdResolver</el-resolver>
</application>

Если вы хотите получить хорошее представление о ElResolver, см. Расширение языка унифицированных выражений Java EE с помощью пользовательского ELResolver

С уважением,

...