【问题标题】:Call to a member function setComponentContext() on null - OctoberCMS在 null 上调用成员函数 setComponentContext() - OctoberCMS
【发布时间】:2019-03-18 12:13:01
【问题描述】:

在过去的几个月里,我一直在学习 PHP 并使用 Octobercms,但我对它还是很陌生。我要实现的基本概念是一个包含 5 个图块的页面。当我单击磁贴时,它会根据您单击的磁贴将当前页面替换为部分页面,并更改 url 而无需重新加载页面。每个图块都有一个 id,其中包含它应该返回的部分名称。例如,设置磁贴有一个data-id="settings"。这是页面截图

page

我为此创建了自己的插件并将组件放置在页面上。在渲染时,它返回有效的仪表板部分,如上面的屏幕截图所示,问题是当我单击另一个图块时。它进行 ajax 调用并在我的组件中调用我的“测试”方法,并传递包含要返回的部分名称的 tile id。我使用方法$this->renderPartial('partialName') 但是我收到以下错误

the error

Call to a member function setComponentContext() on null

以下是我其余代码的屏幕截图:

My 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');
            }
        });

    }



});

My Router.php

<?php

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

My Component

<?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') );
      }

    }

}

我尝试进行一些测试,并认为我已经找到了问题,但我真的不明白如何解决它。这是一些额外的屏幕截图

我转储组件对象 testing component 渲染时看起来不错 onRender 现在它是空的? clicked settings page

【问题讨论】:

    标签: php oop octobercms octobercms-plugins


    【解决方案1】:

    这是错误的处理 Ajax 请求的方式,因为您正在破坏十月 CMS 页面的生命周期。

    您收到错误是因为您直接要求组件处理请求Route::get('/planner/{page}', 'myName\budgetplanner\Components\app@test');

    因为renderpartial 需要控制器上下文,如果你这样做route 肯定会yield unexpected behaviour

    好的,我们明白了,但是,如何正确地做到这一点?


    你的网址可以说我们像这样使用/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>
    

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

    dashboard 的所有其他 tile linksdashboard contentother tile partials 相同。

    现在如果你 click any tile 它将 fire October Ajax framework request 与处理程序 onRenderTiletype (dashboard|tile1|tile2 ...) 所以它会正确调用 October lifecycle methods 并最终通过 onRenderTile 渲染部分并返回 json#tile-area 并作为值将return content of posted partial name(type)

    OctoberCMS ajax framework 足够聪明,它只会用给定的 id 替换此内容,因此它会搜索 #tile-area 并将其内容替换为新内容。

    有关使用 ajax 更新部分的更多信息,您可以阅读以下内容:https://octobercms.com/docs/ajax/update-partials

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

    【讨论】:

    • 谢谢。这正是我一直在寻找的。感谢帮助:)
    猜你喜欢
    • 2017-08-09
    • 2018-04-15
    • 2020-03-10
    • 2017-09-24
    • 2018-02-06
    • 2018-09-29
    • 2018-08-04
    • 2020-03-28
    • 2020-10-28
    相关资源
    最近更新 更多