Php SilverStripe-点击后退按钮时维护下拉选择的内容
我有一个文章列表,可以根据年份下拉列表按年份排序。我问了这个问题,得到了一个惊人的回答,但现在我注意到一个问题:每当用户单击“后退”时,文章列表总是重置为默认视图(即显示所有文章)。但是,下拉列表“记住”用户所做的选择。我希望文章列表与下拉列表中的“选择年份”相匹配,以保持用户的一致性和方便性(我不希望他们每次点击文章上的“后退”按钮时都必须重新选择最初选择的年份) 我知道我可以使用会话变量,但我想知道这是否真的有必要?或者,考虑到代码是如何设置的,这可能是更容易采取的方法 以下是我为NewsReleasesPage模板提供的代码:Php SilverStripe-点击后退按钮时维护下拉选择的内容,php,jquery,silverstripe,Php,Jquery,Silverstripe,我有一个文章列表,可以根据年份下拉列表按年份排序。我问了这个问题,得到了一个惊人的回答,但现在我注意到一个问题:每当用户单击“后退”时,文章列表总是重置为默认视图(即显示所有文章)。但是,下拉列表“记住”用户所做的选择。我希望文章列表与下拉列表中的“选择年份”相匹配,以保持用户的一致性和方便性(我不希望他们每次点击文章上的“后退”按钮时都必须重新选择最初选择的年份) 我知道我可以使用会话变量,但我想知道这是否真的有必要?或者,考虑到代码是如何设置的,这可能是更容易采取的方法 以下是我为NewsR
<?php
class NewsReleasesPage extends Page
{
private static $db = array();
private static $has_one = array();
}
class NewsReleasesPage_Controller extends Page_Controller
{
private static $allowed_actions = array(
'PaginatedReleases',
'YearFilterForm',
'handleYearRequest',
'doFilter',
'year',
'index'
);
public function init()
{
parent::init();
}
public 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;
}
}
//creates a form to filter through news releases by year
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',
'',
$values,
$this->getRequest()->param('ID')
)->setHasEmptyDefault(true)->setEmptyString('Show all')
));
$actions = FieldList::create(array(
FormAction::create('doFilter', 'Submit')
));
return Form::create($this, 'YearFilterForm', $fields, $actions);
}
public function year()
{
return $this->handleYearRequest($this->request);
}
public function index()
{
return $this->handleYearRequest($this->request);
}
//redirects to the proper url depending on which year is selected for sorting news
public function doFilter($data, $form)
{
if (empty($data['Year'])) {
return $this->redirect($this->Link());
} else {
return $this->redirect($this->Link('year/' . $data['Year']));
}
}
//created a paginated list of news released by year
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())->setLimitItems(0);
}
}
然后是呈现列表的SilverStripe模板文件:
<div id="box3" class="clearfix">
<div id="Box-Main-Right" class="clearfix">
<p class="Text-Intro">$H1</p>
$YearFilterForm
</div>
</div>
<div class="Box-LEADING-BRANDS clearfix">
<div class="Box-Main-Right1 clearfix">
<% include ArticleList %>
</div>
</div>
$Form
$H1
$yearFilterPerform
$Form
我认为您遇到了这个问题,因为表单的启动状态与页面加载时的默认状态不同,因此内容(通过JS加载)与表单字段不同步
一种简单的方法是,如果下拉列表值与默认值不同(例如,当它不是空值时),只需通过JS提交表单即可。您可以通过如下更改JS代码来实现这一点:
// handle form submit events
$("#Form_YearFilterForm").on("submit", function(e){
// removed code for brevity
});
// NEW CODE TO ADD
// If the dropdown has a value (eg. is not empty), submit it.
if($("#Form_YearFilterForm select").val()){
$("#Form_YearFilterForm").submit();
}
正确的方法是让JavaScript代码与URL更改一起工作。您可以利用。因此,您可以按如下方式重写JS代码:
;(function($) {
$(function(){
// Establish Variables
var History = window.History,
State = History.getState();
// 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[name="Year"]', function(e){
$("#Form_YearFilterForm").submit();
});
// handle form submit events
$("#Form_YearFilterForm").on("submit", function(e){
e.preventDefault();
var dropdown = $(this).find('select[name="Year"]');
var year = dropdown.val();
// Add a new history state where we keep the year as a property
// and use the urlpattern to build our target URL
History.pushState(
{ year: year },
null,
dropdown.data("urlpattern").replace(/YYYY$/, year)
);
return false;
});
History.Adapter.bind(window, 'statechange', function(){
// Whenever the URL changes, we load the proper data via AJAX
// and set the dropdown value accordingly
State = History.getState();
$('#Form_YearFilterForm select[name="Year"]').val(State.data.year);
$("#ArticleList").addClass("loading");
$.get(
State.url,
function(data, status, xhr){
$("#ArticleList").replaceWith($(data));
}
);
});
// 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);
PHP部分保持不变,除了一个小的添加,我们将所需的URL模式传递给JS。我将其作为HTML5数据属性添加到下拉字段中,但您可以硬编码或以其他方式传递它:
DropdownField::create(
'Year',
'Year',
$values,
$this->getRequest()->param('ID')
)->setHasEmptyDefault(true)
->setEmptyString('Show all')
->setAttribute('data-urlpattern', $this->Link('year') . '/YYYY')
这个稍微复杂一点的解决方案的好处是,它知道URL。因此,您可以使用后退/前进浏览器按钮正常导航,同时仍保留完整的AJAX功能。这正是我想要的!但是,有一个问题……我在控制台中看到了这个错误:History.getState不是一个函数。该功能在其他方面也可以工作,但它似乎打破了jQuery,而jQuery的本意是让提交按钮的使用过时。我不明白这是为什么。看起来一切都设置正确,但是.getState()抛出了一个错误。您是否下载并添加了历史记录JS脚本?看:我尝试了不同的方法,但没有成功。现在我正在使用未压缩目录中的history.js。我用过这个:…确保在jQuery之后和脚本之前加载它。这就成功了!非常感谢你的帮助,我真的很感激!
DropdownField::create(
'Year',
'Year',
$values,
$this->getRequest()->param('ID')
)->setHasEmptyDefault(true)
->setEmptyString('Show all')
->setAttribute('data-urlpattern', $this->Link('year') . '/YYYY')