Почему я могу связать <f: actionListener> с произвольным методом, если он не поддерживается JSF?

Я использую Glassfish 3.1.2.2 и JSF Mojarra 2.1.6.

У меня есть следующая страница Facelets:

<h:form>
  <h:commandLink value="link">
    <f:actionListener binding="#{backingBean.someMethod(1)}"/>
  </h:commandLink>
</h:form>

И следующий боб:

@RequestScoped
@ManagedBean
public class BackingBean {
  public void someMethod(int i) {
    System.out.println("It was called: " + i);
  }
}

Когда я нажимаю на ссылку, в консоли появляется "Информация: она была вызвана: 1".

Документация для binding гласит:

Библиотека: http://xmlns.jcp.org/jsf/core, http://java.sun.com/jsf/core (Jsf Core)

Tag: actionListener

переплет

Выражение привязки значения, которое оценивает объект, который реализует javax.faces.event.ActionListener. [акцент мой]

Кроме того, принятый ответ на этот вопрос гласит, что это невозможно для f:actionListener вызвать произвольный метод.

Почему вызывается метод резервного компонента, если он не поддерживается?

1 ответ

Решение

Это является следствием новой возможности EL 2.2 - вызова метода в выражении значения через #{bean.method()} синтаксис вместо ссылки на свойство только через #{bean.property} синтаксис (который действительно должен быть точного типа ActionListener). Это не сработало бы в EL 2.1 и более ранних версиях, а также не работало бы, когда вы удаляете аргументы и скобки. Этот документ был написан, когда EL 2.2 не существовало (на самом деле он не был изменен по сравнению с версией JSF 1.2 с мая 2006 года; EL 2.2 был представлен в декабре 2009 года). Тем не менее, я согласен с тем, что он нуждается в обновлении в этой части, поскольку это вводит в заблуждение начинающих.

Ответ, который вы нашли, основывался на документе, но ответчик, похоже, не осознавал этого вопроса, binding="#{testController.nodeListener}" не удалось binding="#{testController.nodeListener(event)}" на самом деле работал. Это только не дает вам возможность пройти ActionEvent, Ответ был бы лучше, если бы он предложил просто использовать binding="#{testController.nodeListener()}" вместо этого и получить информацию о событии другим способом, например, позвонив UIComponent#getCurrentComponent() или даже мимоходом #{component} в качестве аргумента. Конечно, только если вам действительно нужна рука.

<h:commandLink value="link">
    <f:actionListener binding="#{bean.someMethod(component)}"/>
</h:commandLink>
public void someMethod(UIComponent component) {
    System.out.println("It was called on: " + component); // HtmlCommandLink
}

Смотрите также:

Другие вопросы по тегам