Ad

Is It Possible To Render A Partial Using Absolute Path?

- 1 answer

I'm developing an OctoberCMS plugin that has a component that renders a different partial depending on the data in the model supplied to the component. The problem I'm having is that I only seem to be able to render a partial if it belongs to a component or the theme partial folder. I'd like to be able to register new model types from other plugins and have their views in the same plugin folder, eg:

  • models
    • mymodel
      • view.htm
    • MyModel.php

I basically want the onRender of the main component to make the decision of which partial to render, eg:

public function onRender()
{
    // Some code here to determine which partial to render

    return $this->renderPartial($pathToPartial);
}
Ad

Answer

Ok then good, we can use 2 engines 1. default PHP and another one is 2. twig

For PHP Engine

First we need to add helper ViewMaker trait in to component

class CompoOne extends ComponentBase
{    
    use \System\Traits\ViewMaker; // <- we need to add partial/view related method makeView

Now we will add two methods render method and custom Render method

As I don't want to override default behavior I will add extension with custom render.

public function customRender() {

    // this will be our logic 
    $partialPath = $this->vars['parialPath'] ?? 'default';
    return $this->makeView($partialPath);
}

public function onRender()
{
    // this will decide which partial we need to render
    $this->vars['parialPath'] = '$/hardiksatasiya/demotest/main';

    // $ <- start from plugin dir
    // $this->vars['parialPath'] = '~/main'; 
    // ~ <- start from root dir

    // data you want to pass to your partial 
    $this->vars['model'] = 'your model';

}

This will let component render its default partialdefault.htm. Now it's code

<h1>Component Parital</h1>
<div class="dynamic-partial">
    {{__SELF__.customRender()|raw }}
<div>

And our custom partial $/hardiksatasiya/demotest/main , it will be like my_project_root_path/plugins + /hardiksatasiya/demotest/main here main will be main.htm automatically so main.htm code

<div class="my-partial">
    Its ok to have partial <?= $model ?>.
</div>

Final out-put for this component will be

<h1>Component Parital</h1>
<div class="dynamic-partial">
    <div class="my-partial">
        Its ok to have partial your model.
    </div>
</div>

Execution Flow

First onRender will be called here we set vars which will contain partial path[you can put it from component config or from else ]

It will call default.htm this will call our custom customRender method

Now we finally call our dynamic partial, inside it all variables will be available which we defined inside $this->vars[] automatically. [ in demo I have added $this->vars['model'] like this ]

For Twig Engine

Just follow PHP engine steps with this instructions

We don't need to add helper ViewMaker trait in to component (so skip that step)

We change our custom Render method to use twig engine

public function customRender() {

    // twig engine
    $partialPath = $partialPath = $this->vars['parialPath'] ?? 'default';
    $partialPath = $partialPath . '.htm';

    if (\File::isPathSymbol($partialPath)) {
        $partialPath = \File::symbolizePath($partialPath);
    }

    $template = $this->controller->getTwig()->loadTemplate($partialPath);
    $partialContent = $template->render($this->vars);

    return $partialContent;
}

Our custom partial file code will be

<div class="my-partial">
    Its ok to have partial {{ model }}
</div>

out-put will be same as above

We can use twig tags here and all the variables which will be assigned to $this->vars will be available inside the partial

If you have any doubt please comment

Ad
source: stackoverflow.com
Ad