Search code examples
cakephpcakephp-3.xcakephp-helper

CakePHP 3 - How to set CSS / Script block inside a View Cell


I'm using CakePHP 3.9

I'm trying to set css / script dependency block inside my view cell.

I want it to be fetched inside the head of my layout, but it just don't work. If I want it to work I must set the css dependency inside the view before/after calling the cell.

Is there any way to set the css dependency inside a View Cell?

My view:

<?= $this->cell('Post::post_input'); ?>
....

My view cell:

<?php echo $this->Html->css(['element/post-input'], ['block' => true]);  ?>
<div class="post-input">...</div>

My Layout:

<html>
<head>
...
    <?php
    echo $this->fetch('css');
    echo $this->fetch('script');
    ?>
...
</head>
<body>
    <?php echo $this->fetch('content'); ?>
</body>
</html>

Solution

  • It doesn't work because a cell is a closed environment that uses a separate view instance, so all blocks that you define in its templates, are going to reside in its internal view.

    From the docs:

    Cell templates have an isolated scope that does not share the same View instance as the one used to render template and layout for the current controller action or other cells. Hence they are unaware of any helper calls made or blocks set in the action’s template / layout and vice versa.

    Cookbook > Views > View Cells > Implementing the Cell

    If you don't want to manually add the CSS block whenever you use the cell, then I would suggest that you build a custom helper that can generate (or even directly echo) the cell and add the block(s), something along the lines of this:

    <?php
    // in src/View/Helper/PostHelper.php
    
    namespace App\View\Helper;
    
    use Cake\View\Helper;
    
    /**
     * @property \Cake\View\Helper\HtmlHelper $Html
     */
    class PostHelper extends Helper
    {
        protected $helpers = [
            'Html'
        ];
    
        protected $wasPostInputCssAdded = false;
    
        public function postInput()
        {
            if (!$this->wasPostInputCssAdded) {
                $this->wasPostInputCssAdded = true;
    
                $this->Html->css(['element/post-input'], ['block' => true]);
            }
    
            return $this->_View->cell('Post::post_input');
        }
    }
    

    The following would then add the block and echo the cell:

    <?= $this->Post->postInput() ?>
    

    See also Cookbook > Views > Helpers > Creating Helpers