Разбиение Freemarker на страницы с параметром поиска

#url #search #pagination #freemarker #http-request-parameters

#url #Поиск #разбивка на страницы #freemarker #http-запрос-параметры

Вопрос:

У меня есть рабочая разбивка на страницы с Fremarker. Вот макрос пейджера:

 <#macro pager url page>
    <#if page.getTotalPages() gt 7>
        <#assign
        totalPages = page.getTotalPages()
        pageNumber = page.getNumber()   1

        head = (pageNumber > 4)?then([1, -1], [1, 2, 3])
        tail = (pageNumber < totalPages - 3)?then([-1, totalPages], [totalPages - 2, totalPages - 1, totalPages])
        bodyBefore = (pageNumber > 4 amp;amp; pageNumber < totalPages - 1)?then([pageNumber - 2, pageNumber - 1], [])
        bodyAfter = (pageNumber > 2 amp;amp; pageNumber < totalPages - 3)?then([pageNumber   1, pageNumber   2], [])

        body = head   bodyBefore   (pageNumber > 3 amp;amp; pageNumber < totalPages - 2)?then([pageNumber], [])   bodyAfter   tail
        >
    <#else>
        <#assign body = 1..page.getTotalPages()>
    </#if>
    <div class="container-fluid mt-3">
        <div class="row">
            <ul class="pagination col">
                <li class="page-item disabled">
                    <a class="page-link" href="#" tabindex="-1">Pages</a>
                </li>
                <#list body as p>
                    <#if (p - 1) == page.getNumber()>
                        <li class="page-item active">
                            <a class="page-link" href="#" tabindex="-1">${p}</a>
                        </li>
                    <#elseif p == -1>
                        <li class="page-item disabled">
                            <a class="page-link" href="#" tabindex="-1">...</a>
                        </li>
                    <#else>
                        <li class="page-item">
                            <a class="page-link" href="${url}?page=${p - 1}amp;size=${page.getSize()}" tabindex="-1">${p}</a>
                        </li>
                    </#if>
                </#list>
            </ul>

            <ul class="pagination col justify-content-end">
                <li class="page-item disabled">
                    <a class="page-link" href="#" tabindex="-1">Elements per page</a>
                </li>
                <#list [20, 40, 80, 120] as c>
                    <#if c == page.getSize()>
                        <li class="page-item active">
                            <a class="page-link" href="#" tabindex="-1">${c}</a>
                        </li>
                    <#else>
                        <li class="page-item">
                            <a class="page-link" href="${url}?page=${page.getNumber()}amp;size=${c}" tabindex="-1">${c}</a>
                        </li>
                    </#if>
                </#list>
            </ul>
        </div>
    </div>
</#macro>
 

И URL-адрес разбиения на страницы выглядит следующим образом:

http://localhost:8080/main?page=1amp;size=10

Для главной страницы есть функция поиска:

 <@c.page>
    <div class="form-row">
        <div class="form-group col-md-6">
            <form method="get" action="/main" class="form-inline">
                <input type="text" name="filter" class="form-control" value="${filter?ifExists}"
                       placeholder="Search by tag"/>
                <button type="submit" class="btn btn-primary ml-2">Search</button>
            </form>
        </div>
    </div>
</@c.page>
 

если поиск введен, URL будет выглядеть как:

http://localhost:8080/main ?фильтр= параметр поиска

Однако разбивка на страницы не работает с URL, который ввел параметр поиска (на самом деле это называется filter).

Пытался добавить что-то вроде следующего к pager.ftl :

 <#if '${url}'?contains("filter")>
    <a class="page-link" href="${url}amp;page=${p - 1}amp;size=${page.getSize()}" tabindex="-1">${p}</a>
<#else>
    <a class="page-link" href="${url}?page=${p - 1}amp;size=${page.getSize()}" tabindex="-1">${p}</a>
</#if>
 

Идея заключалась в том, чтобы проверить URL, установлен ли параметр фильтра -> добавить к нему разбивку на страницы:

http://localhost:8080/main ?filter=search-paramamp;page=1amp;size= 10

Если параметр поиска отсутствует, используйте параметр по умолчанию.

И это не сработало.

Вот полные исходные тексты проекта на GitHub.

Логика бэкэнда с загрузкой Spring и данными Spring работает довольно хорошо.


Попробовал решение @ddekany. Вот результат:

 <#else>
    <li class="page-item">    
        <a class="page-link"
           href="${url}${url?contains('?')?then('amp;', '?')}page=${p - 1}amp;size=${page.getSize()}"
           tabindex="-1">
            ${p}
        </a>
    </li>
</#if>
 

и вторая часть:

 <#else>
    <li class="page-item">
        <a class="page-link"
           href="${url}${url?contains('?')?then('amp;', '?')}page=${page.getNumber()}amp;size=${c}"
           tabindex="-1">
            ${c}
        </a>
    </li>
</#if>
 

Вот когда вы вводите поиск:

введите описание изображения здесь

Однако, когда вы нажимаете 2 страницу поиска, вы будете перенаправлены на главную страницу (поиск пустой, вместо перехода на страницу № 2 результатов поиска):

введите описание изображения здесь


РЕШЕНИЕ:

Правильная настройка URL в контроллере:

 Page<MessageDto> page = messageService.messageList(pageable, filter, user);

if (StringUtils.isNotBlank(filter)) {
    model.addAttribute("url", String.format("/main?filter=%s", filter));
} else {
    model.addAttribute("url", "/main");
}

model.addAttribute("page", page);
model.addAttribute("filter", filter);

return "main";
 

и измените установленный URL-адрес на пейджере:

 <li class="page-item">
    <#--<a class="page-link" href="${url}?page=${p - 1}amp;size=${page.getSize()}" tabindex="-1">${p}</a>-->
    <a class="page-link" href="${url}${url?contains('?')?then('amp;', '?')}page=${p - 1}amp;size=${page.getSize()}" tabindex="-1">
        ${p}
    </a>
</li>
 

и

 <li class="page-item">
    <#--<a class="page-link" href="${url}?page=${page.getNumber()}amp;size=${c}" tabindex="-1">${c}</a>-->
    <a class="page-link" href="${url}${url?contains('?')?then('amp;', '?')}page=${page.getNumber()}amp;size=${c}" tabindex="-1">
        ${c}
    </a>
</li>
 

Закомментированные строки — это старый код. Раскомментированный точно работает.

Вопрос в том, как настроить Fremarker для такой функциональности?

Комментарии:

1. Что вы подразумеваете под «это не сработало»? Кроме того, я бы просто искал ‘?’ вместо ‘filter’. (Но, скорее всего, я бы вообще не стал объединять URL-адреса в шаблон.)

2. В качестве примечания, page.getNumber() , и все это может быть записано как page.number .

3. @ddekany я не сделал того, чего хочу достичь -> когда set и filter имеют значение, которое я хочу сопоставить с разбиением на страницы amp;.... . Если нет параметра фильтра, сопоставьте его следующим образом ?....

4. Вы на самом деле перенаправлены или просто на этот URL-адрес указывает ссылка # 2? В этом случае кажется, что url переменная не содержит ?filter=... части. Не уверен url , откуда берется значение.

Ответ №1:

Проверьте еще раз, потому что #if это должно сработать.

Тем не менее, я бы искал ? , поскольку он более надежен, чем поиск filter , поскольку он работает, даже если параметр позже переименован.

Кроме того, <#if '${url}'?contains('...')> может быть просто записано как <#if url?contains('...')> .

На самом деле, вы, вероятно, не хотите повторять всю эту строку, только для замены одного символа, поэтому просто напишите

href="${url}${url?contains('?')?then('amp;', '?')}page=... .

(Вы можете быстро протестировать такие вещи в демо-версии Freemarker)

Комментарии:

1. Разбивка на страницы перестает работать после этого обновления. Обновленный ответ с поиском кода.

2. @catch23 Удалите <#if url?contains('filter')> тег и соответствующий </#if> тег. Я хотел сказать, что вам не нужно #if , вместо этого вы можете использовать другую вещь с ?then . Кроме того, ваши шансы получить ответы будут намного выше, если вы расскажете, что именно произошло, вместо «перестал работать» и тому подобное.