JSF / Facelets: установить атрибут `action` в динамически вычисляемую строку - PullRequest
2 голосов
/ 06 августа 2009

В моем приложении JSF / Facelets я хочу динамически генерировать цепочку из списка идентификаторов страниц, используя пользовательский тег:

<foo:breadcrumbs trail="foo,bar,baz"/>

Это должно сгенерировать что-то вроде:

<h:commandLink action="foo" ... />
<h:commandLink action="bar" ... />
<!-- (etc.) -->

Мой код выглядит примерно так:

<ui:repeat value="#{fn:split(trail, ',')}" var="key">
    <h:commandLink action="#{key}" ... /> 
</ui:repeat>

Проблема с этим кодом заключается в том, что #{key} интерпретируется как привязка метода. Однако я просто хочу, чтобы строковое значение #{key} было возвращено в качестве результата навигации. Как мне этого добиться?


Единственное, о чем я мог подумать, это создать фиктивный управляемый бин с полем outcome и обработчиком действия, и вызывать его так:

<h:commandLink action="#{dummy.click}" ...>
    <f:setPropertyActionListener target="#{dummy.outcome}" value="#{key}" />
</h:commandLink>

с фиктивным классом, определенным так:

public class Dummy {

    private String outcome;

    public String click() {
        return outcome;
    }

    public void setOutcome(String outcome) {
        this.outcome = outcome;
    }

    public void getOutcome() {
        return outcome;
    }
}

Хотя это кажется уродливым, и я не знаю, сработает ли это.

Ответы [ 3 ]

5 голосов
/ 14 декабря 2009

С тех пор как я задал этот вопрос, я обнаружил очевидное решение, которое очень просто реализовать.

Метод, который является целью действия JSF, не должен принимать аргументов и возвращать строку. Оказывается, у класса String уже есть метод, соответствующий этой сигнатуре - toString()!

Итак, я изменил свой цикл пользовательского интерфейса на следующее:

<ui:repeat value="#{fn:split(trail, ',')}" var="key">
    <h:commandLink action="#{key.toString}" ... /> 
</ui:repeat>

Это позволяет динамически оцениваемой key быть результатом действия JSF и не требует никаких дополнительных классов или уродливых хакерских атак.

3 голосов
/ 06 августа 2009

На ум приходит пара способов.

Вариант 1

Придерживайтесь commandLink и читайте var непосредственно из карты запроса в привязке действия:

public String click() {
  FacesContext context = FacesContext.getCurrentInstance();
  ExternalContext extContext = context.getExternalContext();
  Map<String, Object> reqMap = extContext.getRequestMap();
  return (String) reqMap.get("uirepeatVar");
}

(где ретранслятор имеет атрибут var="uirepeatVar".)


Вариант 2

Переключитесь на outputLink и создайте ссылки GET на сервере:

public List<String> getViewUrls() {
  List<String> views = Arrays.asList("/index.xhtml", "/idtable.xhtml");

  List<String> urls = new ArrayList<String>();
  FacesContext context = FacesContext.getCurrentInstance();
  Application application = context.getApplication();
  ViewHandler viewHandler = application.getViewHandler();
  for (String view : views) {
    String url = viewHandler.getActionURL(context, view);
    urls.add(url);
  }
  return urls;
}

Вид:

<ui:repeat value="#{breadcrumbBean.viewUrls}" var="url">
  <h:outputLink value="#{url}">#{url}</h:outputLink> <br />
</ui:repeat>
1 голос
/ 06 августа 2009

Почему бы вам не создать пользовательский компонент, который генерирует объекты h: commandLink программно? Вероятно, это будет «самое чистое» решение.

...