在过去的几个月里,我一直在学习PHP并使用Octobercms,而且我对它还很陌生。我试图实现的基本概念是一个包含5个瓷砖的页面。当我单击“平铺”时,它将当前页替换为“部分”,这取决于您单击了哪个瓷砖,并更改了url,而不必重新加载该页。每个瓷砖都有一个id,其名称为它应该返回的部分的名称。例如,设置瓷砖有一个data-id="settings"。这是页面的截图
我已经为此创建了自己的插件,并将组件放在页面上。在呈现时,它返回仪表板部分,它可以在上面的屏幕截图中显示,问题是当我单击另一个瓷砖时。它进行ajax调用,并在组件中调用我的"test“方法,并传递包含要返回的部分的名称的平铺id。我使用了$this->renderPartial('partialName')方法,但是我得到了以下错误
Call to a member function setComponentContext() on null下面是我剩下的代码的截图:
$( document ).ready(function() {
$(document).on('click','.tile',function() {
let page = $(this).attr('id');
history.pushState({page}, '', 'planner/' + page );
getPage(page);
});
window.onpopstate = function(e){
if(e.state){
getPage(e.state.id);
}
};
history.replaceState({page: null}, 'Default state', './planner');
function getPage (page) {
$.ajax({
url: '/planner/' + page,
type: 'GET',
success: function(data){
$('.page-container').html(data);
},
error: function(data) {
console.log('Could not return page');
}
});
}
});<?php
Route::get('/planner/{page}', 'myName\budgetplanner\Components\app@test');<?php
namespace myName\budgetplanner\Components;
use Db;
class app extends \Cms\Classes\ComponentBase
{
public function componentDetails()
{
return [
'name' => 'budgetplanner',
'description' => 'Manage your finances.'
];
}
public function onRender()
{
echo ( $this->renderPartial('@dashboard.htm') );
}
public function test($page)
{
if ($page == 'undefined') {
echo ( $this->renderPartial('@dashboard.htm') );
}
elseif ($page == 'overview') {
echo ( $this->renderPartial('@overview.htm') );
}
elseif ($page == 'month') {
echo ( $this->renderPartial('@month.htm') );
}
elseif ($page == 'reports') {
echo ( $this->renderPartial('@reports.htm') );
}
elseif ($page == 'budget') {
echo ( $this->renderPartial('@budget.htm') );
}
elseif ($page == 'settings') {
echo ( $this->renderPartial('@settings.htm') );
}
}
}我试着做了一些测试,并认为我已经找到了问题,但我真的不知道如何着手解决它。以下是一些额外的截图
发布于 2018-10-15 12:48:30
这是处理Ajax请求的错误方式,因为您正在破坏10月CMS页面的生命周期。
因为直接要求组件处理请求Route::get('/planner/{page}', 'myName\budgetplanner\Components\app@test');,所以出现了错误。
由于renderpartial需要控制器上下文,如果您这样做route,它肯定会yield unexpected behaviour
好的,我们知道了,但是,如何正确地做它呢?
您的url让我们说我们使用的是这样的
/planner/:type

为ajax框架添加框架和额外的布局,确保在脚本之前添加它们。
<script src="{{ 'assets/javascript/jquery.js'|theme }}"></script>
{% framework extras %}您的脚本应该如下所示
<script>
$(document).ready(function() {
$(document).on('click','.tile',function() {
let page = $(this).attr('data-tile');
history.pushState({page}, '', '/planner/' + page );
getPage(page);
});
window.onpopstate = function(e){
if(e.state){
getPage(e.state.page);
}
};
// not sure causing issues so commented
// history.replaceState({page: null}, 'Default state', './planner');
function getPage (page) {
$.request('onRenderTile', { data: { type: page }})
}
});
</script>你的组件
public function onRender()
{
// if type is not passed default would be dashboard
$type = $this->param('type', 'dashboard');
return $this->onRenderTile($type)['#tile-area'];
}
public function onRenderTile($type = null)
{
$availableTiles = [
'dashboard',
'tile1',
'tile2',
'tile3',
];
// if not passed any value then also check post request
if(empty($type)) {
$type = post('type');
}
// we check partial is valid other wise just return dashboard content
if(in_array($type, $availableTiles)) {
return ['#tile-area' => $this->renderPartial('@'.$type.'.htm')];
}
else {
return ['#tile-area' => $this->renderPartial('@dashboard.htm')];
}
}你的露台
文件:_tiles.htm
<div class="tile" data-tile="dashboard">Dashboard</div>
<div class="tile" data-tile="tile1">Tile 1</div>
<div class="tile" data-tile="tile2">Tile 2</div>
<div class="tile" data-tile="tile3">Tile 3</div>文件: dashboard.htm
<div id="tile-area">
{% partial __SELF__~"::_tiles" %}
<h1>Dashboard</h1>
</div>文件: tile1.htm
<div id="tile-area">
{% partial __SELF__~"::_tiles" %}
<h1>Tile 1 Content</h1>
</div>文件: tile2.htm
<div id="tile-area">
{% partial __SELF__~"::_tiles" %}
<h1>Tile 2 Content</h1>
</div>文件: tile3.htm
<div id="tile-area">
{% partial __SELF__~"::_tiles" %}
<h1>Tile 3 Content</h1>
</div>最初,如果没有传递
default partial dashboard,它将呈现type。
dashboard拥有与other tile partials相同的所有其他tile links和dashboard content。
现在,如果您使用click any tile,它将使用处理程序onRenderTile和type (dashboard|tile1|tile2 ...)来实现fire October Ajax framework request,因此它将正确地调用October lifecycle methods,并最终通过onRenderTile呈现出部分,并使用密钥#tile-area返回json,并且作为值它将return content of posted partial name(type)
OctoberCMS ajax framework非常聪明,它只需要用just id替换这个内容,所以它将搜索#tile-area并用新的内容替换它的内容。
有关使用ajax更新部分的更多信息,可以阅读以下内容:https://octobercms.com/docs/ajax/update-partials
如有任何疑问或疑问,请评论。
https://stackoverflow.com/questions/52793485
复制相似问题