php-SilverStripe-根据下拉选择创建分页
作者:互联网
我正在为SilverStripe网站上的页面建立一些分页,该页面默认情况下首先显示所有文章,但用户可以通过从下拉控件中选择年份来选择要查看的文章.
这是文章的模板.现在,我有适当的代码可以在页面首次加载或重新加载并且从服务器获取所有文章时添加分页:
<select id="SelectNewsYear">
<option value="">Select a year</option>
<% loop $GroupedNewsByDate.GroupedBy(PublishYear) %>
<option value="$PublishYear">$PublishYear</option>
<% end_loop %>
<option value="all">Show all</option>
</select>
<br /><br />
<div class="RecentNews">
<% loop $PaginatedReleases %>
$ArticleDate.format("F j, Y"), <a href="$URLSegment">$H1</a><br />
<% end_loop %>
<% if $PaginatedReleases.MoreThanOnePage %>
<% if $PaginatedReleases.NotFirstPage %>
<a class="prev" href="$PaginatedReleases.PrevLink">Prev</a>
<% end_if %>
<% loop $PaginatedReleases.Pages %>
<% if $CurrentBool %>
$PageNum
<% else %>
<% if $Link %>
<a href="$Link">$PageNum</a>
<% else %>
...
<% end_if %>
<% end_if %>
<% end_loop %>
<% if $PaginatedReleases.NotLastPage %>
<a class="next" href="$PaginatedReleases.NextLink">Next</a>
<% end_if %>
<% end_if %>
</div>
Page.php中的PaginatedReleases函数:
//Returns a paginted list of news releases
public function PaginatedReleases(){
$newslist = NewsReleaseArticlePage::get()->sort('ArticleDate', "DESC");
return new PaginatedList($newslist, $this->getRequest());
}
现在的问题是,从下拉列表中选择每年时,如何维护分页功能.最初,我不关心分页,因为我更关心下拉列表的功能.这是我当前设置的jQuery和AJAX代码,可从下拉列表中获取年份值并将其传递给服务器并传递给适当的函数:
(function($) {
$(document).ready(function() {
var SelectNewsYear = $('#SelectNewsYear');
var month = new Array();
month[0] = "January";
month[1] = "February";
month[2] = "March";
month[3] = "April";
month[4] = "May";
month[5] = "June";
month[6] = "July";
month[7] = "August";
month[8] = "September";
month[9] = "October";
month[10] = "November";
month[11] = "December";
SelectNewsYear.change(function() {
if (SelectNewsYear.val() != "" && SelectNewsYear.val() != null && SelectNewsYear.find('option:selected').attr('value') !="all") {
sendYear();
}
else{
showAll();
}
});
//get all articles by the year selected
function sendYear(){
var year = SelectNewsYear.find('option:selected').attr('value');
$.ajax({
type: "POST",
url: "/home/getNewsByYear/"+year,
dataType: "json"
}).done(function (response) {
var list = '';
var newsSection = $('.RecentNewsByYear');
for (var i=0;i<response.length;i++){
var newsDate = new Date(response[i].date);
var monthFullName = month[newsDate.getUTCMonth()];
list += monthFullName + " " + newsDate.getUTCDate() +", " +newsDate.getFullYear() + ', ' + '<a href="' + response[i].article + '"target="_blank">' + response[i].title +"</a> <br />";
}
newsSection.empty();
newsSection.append(list);
});
}
});
}(jQuery));
$= jQuery.noConflict();
还有Page.php的getNewsByYear函数:
//Get all recent news by year based on selected year from dropdown
public function getNewsByYear(){
//Get the year selected by the dropdown
$newsReleaseYear = $this->getRequest()->param('ID');
//Group together all news that are associated with that selected year
$newsReleases = NewsReleaseArticlePage::get();
$return = array();
//put the news releases into the array that match the selected year
foreach($newsReleases as $newsRelease){
$newsDate = date("Y", strtotime($newsRelease->ArticleDate));
if($newsDate == $newsReleaseYear){
$return[] = array(
'title' => $newsRelease->H1,
'date' => $newsRelease->ArticleDate,
'article' => $newsRelease->URLSegment
);
}
}
return json_encode($return);
}
getNewsByYear函数可以正常运行,但是我不确定如何在此处合并SilverStripe PaginationList功能.我想知道是否有一种方法可以不依赖json编码的数据而返回选定的文章?
解决方法:
当您返回JSON从JSON构建HTML标记时,肯定还有改进的空间.
我还认为,以无需JS的方式编写应用程序逻辑,然后添加JS来逐步增强您的应用程序是一种好习惯.这样,您就不会锁定每个非JS设备/阅读器/用户.
所以这就是我要做的(准备广泛回答):
启用按年份过滤
首先,您希望能够按年份筛选记录.我认为您启用通过URL过滤的方法很好,所以这就是我们要做的:
1.获取分页列表,可以按年份过滤
在您的控制器中,添加/修改以下方法:
public function PaginatedReleases($year = null)
{
$list = NewsReleaseArticlePage::get()->sort('ArticleDate', 'DESC');
if ($year) {
$list = $list->where(array('YEAR("ArticleDate") = ?' => $year));
}
return PaginatedList::create($list, $this->getRequest());
}
这将允许您通过传递$year参数来获取所有条目,或仅获取特定年份的条目.
2.向您的控制器添加年度操作
public static $allowed_actions = array(
'year' => true
);
public function year()
{
$year = $this->request->param('ID');
$data = array(
'Year' => $year,
'PaginatedReleases' => $this->PaginatedReleases($year)
);
return $data;
}
运行dev / build后,您应该已经能够通过更改URL(例如,mypage / year / 2016或mypage / year / 2015等)按年份过滤条目.
使用带下拉菜单的表格进行过滤
将以下内容添加到您的控制器以创建一个表单来过滤您的条目:
public function YearFilterForm()
{
// get an array of all distinct years
$list = SQLSelect::create()
->addFrom('NewsReleaseArticlePage')
->selectField('YEAR("ArticleDate")', 'Year')
->setOrderBy('Year', 'DESC')
->addGroupBy('"Year"')->execute()->column('Year');
// create an associative array with years as keys & values
$values = array_combine($list, $list);
// our fields just contain the dropdown, which uses the year values
$fields = FieldList::create(array(
DropdownField::create(
'Year',
'Year',
$values,
$this->getRequest()->param('ID')
)->setHasEmptyDefault(true)->setEmptyString('(all)')
));
$actions = FieldList::create(array(
FormAction::create('doFilter', 'Submit')
));
return Form::create($this, 'YearFilterForm', $fields, $actions);
}
实现doFilter函数.它只是根据选择的年份重定向到正确的URL:
public function doFilter($data, $form)
{
if(empty($data['Year'])){
return $this->redirect($this->Link());
} else {
return $this->redirect($this->Link('year/' . $data['Year']));
}
}
不要忘记将表单名称添加到allowed_actions中:
public static $allowed_actions = array(
'YearFilterForm' => true, // <- this should be added!
'year' => true
);
现在删除您的< select>输入模板中的输入字段,并将其替换为:$YearFilterForm.
运行dev / build后,您应该拥有一个页面,该页面的格式允许按年份进行过滤(使用分页)
启用AJAX
使用AJAX,我们希望能够仅加载页面的更改部分.因此,要做的第一件事是:
1.为应该异步加载的内容创建一个单独的模板
创建一个模板Includes / ArticleList.ss
<div id="ArticleList" class="RecentNews">
<% loop $PaginatedReleases %>
$ArticleDate.format("F j, Y"), <a href="$URLSegment">$H1</a><br />
<% end_loop %>
<% if $PaginatedReleases.MoreThanOnePage %>
<% if $PaginatedReleases.NotFirstPage %>
<a class="prev pagination" href="$PaginatedReleases.PrevLink">Prev</a>
<% end_if %>
<% loop $PaginatedReleases.Pages %>
<% if $CurrentBool %>
$PageNum
<% else %>
<% if $Link %>
<a href="$Link" class="pagination">$PageNum</a>
<% else %>
...
<% end_if %>
<% end_if %>
<% end_loop %>
<% if $PaginatedReleases.NotLastPage %>
<a class="next pagination" href="$PaginatedReleases.NextLink">Next</a>
<% end_if %>
<% end_if %>
</div>
然后可以将页面模板简化为:
$YearFilterForm
<% include ArticleList %>
开发/构建后,一切都应该像以前一样工作.
2.通过AJAX请求页面时,提供部分内容
由于这会影响对年份和索引(未过滤的条目)的调用,因此请在您的控制器中创建一个帮助方法,如下所示:
protected function handleYearRequest(SS_HTTPRequest $request)
{
$year = $request->param('ID');
$data = array(
'Year' => $year,
'PaginatedReleases' => $this->PaginatedReleases($year)
);
if($request->isAjax()) {
// in case of an ajax request, render only the partial template
return $this->renderWith('ArticleList', $data);
} else {
// returning an array will cause the page to render normally
return $data;
}
}
然后,您可以添加/修改index和year方法,使其看起来相同:
public function year()
{
return $this->handleYearRequest($this->request);
}
public function index()
{
return $this->handleYearRequest($this->request);
}
3.用JavaScript串连所有内容
(function($) {
$(function(){
// hide form actions, as we want to trigger form submittal
// automatically when dropdown changes
$("#Form_YearFilterForm .Actions").hide();
// bind a change event on the dropdown to automatically submit
$("#Form_YearFilterForm").on("change", "select", function (e) {
$("#Form_YearFilterForm").submit();
});
// handle form submit events
$("#Form_YearFilterForm").on("submit", function(e){
e.preventDefault();
var form = $(this);
$("#ArticleList").addClass("loading");
// submit form via ajax
$.post(
form.attr("action"),
form.serialize(),
function(data, status, xhr){
$("#ArticleList").replaceWith($(data));
}
);
return false;
});
// handle pagination clicks
$("body").on("click", "a.pagination", function (e) {
e.preventDefault();
$("#ArticleList").addClass("loading");
$.get(
$(this).attr("href"),
function(data, status, xhr){
$("#ArticleList").replaceWith($(data));
}
);
return false;
});
});
})(jQuery);
结论
您现在有了一个可以在非JS设备上正常降级的解决方案.通过下拉列表和分页进行过滤已启用AJAX.标记未在JS和模板中定义,仅由SilverStripe模板负责标记.
剩下要做的就是在内容刷新时添加一个不错的加载动画;)
标签:silverstripe,pagination,php,jquery 来源: https://codeday.me/bug/20191027/1940732.html