Пользовательский компонент JSF 2 с h: commandLink внутри ui: repeat

Я разработал собственный компонент (вдохновленный этой статьей от BalusC), который содержит тег ui:repeat, отображающий список интерактивных страниц таблицы.
Внутри блока цикла есть h:commandLink, который асинхронно вызывает действие, отправляя параметр. Значение параметра изменяется в каждом цикле. Вот код страницы:

[...]
<ui:repeat value="#{cc.attrs.pager.pages}" var="loopPage">
    <li>
        <h:commandLink 
            action="#{cc.attrs.pager.changePage}"
            value="#{loopPage}"
            rendered="#{loopPage != cc.attrs.pager.currentPage}"
            immediate="true"
        >
            <f:param name="selectedPage" value="#{loopPage}" />
            <f:ajax execute="@this" render="#{cc.attrs.render}" />
        </h:commandLink>

        <h:outputText 
            value="#{loopPage}" 
            rendered="#{loopPage == cc.attrs.pager.currentPage}"
        />
    </li>
</ui:repeat>
[...]

Теперь атрибут компонента cc.attrs.pager указывает на то, что вспомогательный компонент с областью видимости, атрибуты pages и currentPage которого видны через геттеры, а changePagemethod — это действие, которое нужно вызвать. Атрибут компонента cc.attrs.render является целью, которая будет обновляться после каждого выполнения действия. Вот соответствующий код компонента:

[...]

private Integer[] pages;
private int currentPage;

[...]

public Integer[] getPages() {
    return pages;
}

public int getCurrentPage() {
    return currentPage;
}

[...]

public void changePage() {
    HttpServletRequest request = (HttpServletRequest) FacesContext
        .getCurrentInstance()
        .getExternalContext()
        .getRequest()
    ;

    String page = request.getParameter("selectedPage");
    changePage(Integer.valueOf(page) * rowsPerPage);
}

public void changePage(int firstRow){
    this.firstRow = firstRow; //Set the first result to be returned
    loadDataList(); // Load requested page.
}

[...]

Первоначальный рендеринг идеален: все ссылки на страницы отображаются правильно, а текущий номер страницы не связан, как хотелось бы. Проблема проявляется при переходе на другую страницу: ничего не происходит.
Хотя действие h:commandLink отправляется с точным значением параметра цикла, ответ всегда возвращает одну и ту же страницу (первую). Отладив его, я заметил, что выполнение не входит ни в один из двух методов changePage. Я не уверен, связана ли эта проблема с ui:repeat, но опуская ее, я могу сказать, что тот же механизм работает и для других целей.

Любое предложение?


person ruphus    schedule 28.12.2011    source источник


Ответы (1)


Я думаю, вам стоит попробовать заменить <ui:repeat> на <c:forEach>

person Mr.J4mes    schedule 28.12.2011
comment
Спасибо за ответ. Не могли бы вы объяснить мне, почему я должен это делать? - person ruphus; 28.12.2011
comment
Это работает? Если вы используете Mojarra, <ui:repeat> содержит ошибки. Вы не должны использовать его. - person Mr.J4mes; 28.12.2011
comment
На самом деле я использую Mojarra 2.0.6. Ошибка должна быть этой. Решение, которое вы даете, отлично работает. Спасибо за поддержку! - person ruphus; 28.12.2011
comment
Еще одна проблема: при использовании c:forEach на cc.attrs.pager.pages рендеринг первой страницы ничего не показывает. Я думаю, это потому, что коллекция еще не инициализирована при оценке c:forEach. Это правильно? - person ruphus; 31.12.2011
comment
Проблема, похоже, присутствует и в Mojarra 2.1.6. - person ruphus; 15.02.2012