首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用null - OctoberCMS上的成员函数OctoberCMS()

调用null - OctoberCMS上的成员函数OctoberCMS()
EN

Stack Overflow用户
提问于 2018-10-13 13:34:41
回答 1查看 572关注 0票数 0

在过去的几个月里,我一直在学习PHP并使用Octobercms,而且我对它还很陌生。我试图实现的基本概念是一个包含5个瓷砖的页面。当我单击“平铺”时,它将当前页替换为“部分”,这取决于您单击了哪个瓷砖,并更改了url,而不必重新加载该页。每个瓷砖都有一个id,其名称为它应该返回的部分的名称。例如,设置瓷砖有一个data-id="settings"。这是页面的截图

页面

我已经为此创建了自己的插件,并将组件放在页面上。在呈现时,它返回仪表板部分,它可以在上面的屏幕截图中显示,问题是当我单击另一个瓷砖时。它进行ajax调用,并在组件中调用我的"test“方法,并传递包含要返回的部分的名称的平铺id。我使用了$this->renderPartial('partialName')方法,但是我得到了以下错误

误差

代码语言:javascript
复制
Call to a member function setComponentContext() on null

下面是我剩下的代码的截图:

我的Javascript

代码语言:javascript
复制
$( 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');
            }
        });

    }



});

我的Router.php

代码语言:javascript
复制
<?php

Route::get('/planner/{page}', 'myName\budgetplanner\Components\app@test');

我的组件

代码语言:javascript
复制
<?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') );
      }

    }

}

我试着做了一些测试,并认为我已经找到了问题,但我真的不知道如何着手解决它。以下是一些额外的截图

我将组件对象测试组件转储到呈现上,它看起来很好,现在它是空的?单击设置页

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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框架添加框架和额外的布局,确保在脚本之前添加它们。

代码语言:javascript
复制
<script src="{{ 'assets/javascript/jquery.js'|theme }}"></script>
{% framework extras %}

您的脚本应该如下所示

代码语言:javascript
复制
<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>

你的组件

代码语言:javascript
复制
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

代码语言:javascript
复制
<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

代码语言:javascript
复制
<div id="tile-area">
    {% partial __SELF__~"::_tiles" %}
    <h1>Dashboard</h1>
</div>

文件: tile1.htm

代码语言:javascript
复制
<div id="tile-area">
    {% partial __SELF__~"::_tiles" %}
    <h1>Tile 1 Content</h1>
</div>

文件: tile2.htm

代码语言:javascript
复制
<div id="tile-area">
    {% partial __SELF__~"::_tiles" %}
    <h1>Tile 2 Content</h1>
</div>

文件: tile3.htm

代码语言:javascript
复制
<div id="tile-area">
    {% partial __SELF__~"::_tiles" %}
    <h1>Tile 3 Content</h1>
</div>

最初,如果没有传递default partial dashboard,它将呈现type

dashboard拥有与other tile partials相同的所有其他tile linksdashboard content

现在,如果您使用click any tile,它将使用处理程序onRenderTiletype (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

如有任何疑问或疑问,请评论。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52793485

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档