Получение другого идентификатора клиента компонента в JSF 2.0 - программирование
Подтвердить что ты не робот

Получение другого идентификатора клиента компонента в JSF 2.0

Есть ли в JSF 2.0 встроенный метод для поиска идентификатора клиента другого компонента? На SO есть около тысячи вопросов, связанных с идентификатором клиента, и есть много хакерских методов для этого, но мне интересно, предоставил ли JSF 2.0 более простой метод, который я просто не знаю.

#{component.clientId} оценивает данный идентификатор клиента собственного компонента, но я хочу ссылаться на другой идентификатор компонента.

В этом сообщении в блоге упоминается component.clientId, а также говорится, что #{someComponent.clientId} работает, но из того, что я могу сказать, это не так. Я считаю, что он написал, что до того, как были выпущены какие-либо ссылочные версии JSF 2.0, он просто шел по JSR и, возможно, эта функциональность изменилась. Я не уверен.

Я знаю, что PrimeFaces и RichFaces имеют свои собственные функции для возврата идентификатора клиента, но мне просто интересно, есть ли для этого встроенный метод JSF 2.0. Вот несколько примеров:

Это работает для возврата идентификатора outputText.

`<h:outputText value="My client ID : #{component.clientId}" />`

Согласно сообщению выше, это должно работать, но это не так. Я просто не получаю выход.

`<h:button id="sampleButton" value="Sample" />`

`<h:outputText value="sampleButton client ID : #{sampleButton.clientId}" />`

Это работает в PrimeFaces:

`<h:outputText value="PrimeFaces : sampleButton client ID : #{p:component('sampleButton')}" />` 

Работает в RichFaces:

`<h:outputText value="RichFaces : sampleButton client ID : #{rich:clientId('sampleButton')}" />`

Кроме того, если это вообще возможно, я ищу решения, которые не будут прерываться, если я изменю значение javax.faces.SEPARATOR_CHAR или добавлю/удалю контейнеры вне ссылочных компонентов. Я потратил много времени на устранение проблем, вызванных жестко закодированными идентификационными путями.

4b9b3361

Ответ 1

Вам необходимо назначить компоненту имя переменной в области видимости атрибутом binding.

<h:button id="sampleButton" binding="#{sampleButton}" value="Sample" />
<h:outputText value="sampleButton client ID : #{sampleButton.clientId}" />

Ответ 2

Это сработало для меня. Мне было бы интересно узнать, нормально ли писать такой ответ.

client.html

<h:outputText value="#{UIHelper.clientId('look-up-address-panel-id')}" />

UIHelper.java

@ManagedBean(name = "UIHelper", eager = true)
@ApplicationScoped
public class UIHelper
{

public String clientId(final String id)
{
  FacesContext context = FacesContext.getCurrentInstance();
  UIViewRoot root = context.getViewRoot();
  final UIComponent[] found = new UIComponent[1];
  root.visitTree(new FullVisitContext(context), new VisitCallback()
  {
    @Override
    public VisitResult visit(VisitContext context, UIComponent component)
    {
      if (component.getId().equals(id))
      {
        found[0] = component;
        return VisitResult.COMPLETE;
      }
      return VisitResult.ACCEPT;
    }
  });
  return found[0] == null ? "" : "#" + found[0].getClientId().replace(":", "\\\\:");
}

}

Ответ 3

Поскольку это было одним из первых результатов моего поиска в Google, и я задавался вопросом, почему я получил

javax.el.PropertyNotFoundException(свойство 'itemId' не найдено [...])

при попытке принять решение, я хотел бы поделиться своим решением для JSF 1.2:

Для метода UIComponent getClientId нужен параметр FacesContext (см. Документация UIComponent). Поэтому добавьте привязку к резервной копии bean, а также другой метод, который возвращает clientId:

XHTML:

<h:button id="sampleButton" binding="#{backingBean.sampleButton}" value="Sample" />
<h:outputText value="sampleButton client ID : #{backingBean.sampleButtonClientId}" />

Bean:

private UIComponent sampleButton;

public UIComponent getSampleButton() {
    return sampleButton;
}

public void setSampleButton(final UIComponent sampleButton) {
    this.sampleButton = sampleButton;
}

public String getSampleButtonClientId() {
    final FacesContext context = FacesContext.getCurrentInstance();
    return sampleButton.getClientId(context);
}

Обратите внимание, что bean, с которым вы привязываете свой компонент, должен быть указан в области запроса, иначе вы можете получить java.lang.IllegalStateException (duplicate Id for a component) (сравнить с этот раздел).