#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
. Кроме того, ваши шансы получить ответы будут намного выше, если вы расскажете, что именно произошло, вместо «перестал работать» и тому подобное.