Подтвердить что ты не робот

Как частично перезагрузить ui: repeat?

У нас есть веб-приложение, построенное на JBoss 7.1 с JSF2 и Primefaces 3.3.

На одной из наших страниц есть ui:repeat, отображающий 10 элементов; то пользователь может нажать на какую-то кнопку "показать больше" , и через ajax будет отображаться еще 10 элементов. Пользователь может нажать кнопку "показать больше" , пока не появится больше предметов для показа. Примечание. Это не разбиение на страницы, отображаемый список увеличивается с каждым нажатием кнопки "показать больше" .

Фактически, когда пользователь нажимает кнопку, сервер возвращает старые элементы и новые, а клиентская сторона JSF должна каждый раз перестраивать весь ретранслятор через jQuery.

Мы хотели бы найти лучшее и более эффективное решение. Старые элементы не изменяются между n-1 и n-м вызовами, поэтому было бы более эффективно, если бы сервер мог возвращать только через ajax 10 новых элементов.

Возможно ли это в JSF2? JSF, похоже, не соответствует этому рекурсивному рендерингу. Единственным компонентом, который может помочь нам, будет компонент TreeNode, но он выглядит немного взломанным: -/

4b9b3361

Ответ 1

В стандартном API JSF ничего подобного нет. Также ничего не приходит в голову в PrimeFaces.

OmniFaces <o:componentIdParam> может быть именно то, что вы ищете. Это позволяет вам разрешить JSF отображать только подмножество дерева компонентов на основе определенного параметра запроса, который может быть идентификатором компонента или идентификатором клиента. Вы могли бы просто использовать jQuery $.get(), чтобы перезагрузить <ui:repeat> вместе с начальным индексом в качестве параметра запроса и использовать jQuery $.append(), чтобы добавить его в HTML DOM.

Вот полный пример запуска. Вид:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:o="http://omnifaces.org/ui"
>
    <f:metadata>
        <o:componentIdParam componentIdName="componentId" />
    </f:metadata>
    <h:head>
        <title>Qaru Question 11364006</title>
        <script src="http://code.jquery.com/jquery-latest.min.js"></script> <!-- Substitute with PrimeFaces' one, if necessary. -->
    </h:head>
    <h:body>
        <ul id="items">
            <ui:repeat id="itemsRepeater" value="#{bean.items}" var="item">
                <li>#{item}</li>
            </ui:repeat>
        </ul>
        <input type="button" id="showMore" value="Show more"/>
        <h:outputScript>
            $("#showMore").click(function() {
                $items = $("#items");
                var params = { start: $items.find("li").length, componentId: "itemsRepeater" };
                $.get(location, params, function(html) {
                    $items.append(html);
                });
            });
        </h:outputScript>   
    </h:body>
</html>

Поддержка bean:

@ManagedBean
@RequestScoped
public class Bean {

    private List<String> items;

    @ManagedProperty("#{param.start}")
    private int start;

    @PostConstruct
    public void init() {
        // Just a stub. Do your thing to fill the items.
        items = new ArrayList<String>();
        int size = start + 10;

        for (int i = start; i < size; i++) {
            items.add("item " + (i + 1));
        }
    }

    public void setStart(int start) {
        this.start = start;
    }

    public List<String> getItems() {
        return items;
    }

}

Обновить: демонстрацию live можно найти в примере "Расширяемый список" страницы <o:componentIdParam> текущей витрины приложение.

Ответ 2

В подобных ситуациях я полностью обойду JSF и использую JAX-RS-сервис с jQuery AJAX. Такой подход поможет вам создавать гораздо лучшие приложения, чем просто поддержка AJAX от JSF. Вот основная методика.

На странице XHTML просто укажите местозаполнитель для списка:

<div id="item_list"></div>

<a href="#" onclick="loadNext();">Load more...</a>

Когда страница загружается, сделайте запрос AJAX для заполнения начального списка. Вот пример кода. Могут быть опечатки, но вы получаете идею.

var nextStart = 0;

$(function() {
    loadNext();
});

function loadNext() {
    $.ajax({
        type: "GET",
        url: "api/items?start=" + nextStart,
        success: function(data) {
            appendToList(data);
            nextStart += data.length;
        }
    });
}

function appendToList(data) {
    //Iterate through data and add to DOM
    for (var i = 0; i < data.length; ++i) {
        $("#item_list").append($("<p>", {text: data.productName}));
    }
}