Linking to other Components Partial

I wonder a bit if I missunderstood the linking to partials.

If I just use {% partial “mypartial” %}, it’ll look in the active themes partial folder for mypartial.htm

If the path argument is “myfolder/mypartial”, it looks for the same file inside the folder “myfolder” within the themes partials.

So far so good.

Now I try to render other partials from inside my components default.htm partial.

Sure I could render partials wroted in the theme, but it seems wrong to have a themes dependencies from inside my plugins component. So ofc I try to store those additional component partials inside the components partial folder.

Which works fine… most of the time.

For ex:
Within the component “tagtree”, I have the default.htm which links to the tag.htm partial with this code:
{% partial “tagtree::tag” tag=tag %}

Works fine.

But if I would like to render this tag.htm partial from another component of the same plugin, it doesnt work. I wonder why. Is this not supported or did I miss something?

Or should I create a “partial” folder inside my plugin and put the partials there and link to it from the components partials … somehow?

Any support is welcome. Thanks a lot ^^

Does it work, when you give the full path to your partial? Something like this:

{% partial "~/plugins/acme/plugin_name/components/component_name/partial.htm" %}
1 Like

Hi maki,

thanks for the reply.

I tried it out, but having the ~ in the name creates an error:

An exception has been thrown during the rendering of a template ("Invalid file name: ~/plugins/mch/myplugin/components/tagtree/branches.htm. File names can contain only alphanumeric symbols, underscores, dashes and dots. Some examples of correct file names: page.htm, page, subdirectory/page").

I tried around a bit without the “~/” in the beginning, but couldnt get it to work.

Components should not reference partials from other components. Consider using Laravel views here, with the {% include %} Twig tag…

An example file plugins/acme/plugin_name/views/tag.htm can be included in Twig with:

{% include 'acme.plugin_name::tag' %}
1 Like

If you have a plugin with multiple components that are sharing partials, you can use the specific folder partials inside the components folder, and insert your shared partial there.
You can access them using {% partial '@tag' %}
with the following structure then: author/acme/components/partials/tag.htm

2 Likes

Thanks a lot you two!

Both solutions worked, but chris solution works perfect for my needs since I’ve multiple components and they should share some partials. So now, all components have the default.htm and one folder INSIDE the components folder with the shared partials.

That’s perfect.

Thanks a lot, problem solved ^^

Oh btw: I dont remember seeing this anywhere in the docu. Did I miss it?

Perhaps. Here is the docs link: Component Partials

1 Like

I found another way. Might not be an optimal way, but it does it’s job.

Basically I have a component rendering a sidebar box (Bootstrap Card) which I would like to fill dynamically with title and content and place it within the sidebar.

If I call the component directly, it looks like this:

[sidebar]
title = '...'
content = '...'
==
{% component 'sidebar' %}

Since I would like to render content within those boxes from multiple other plugins as a kind of preview and I also use partials from there, I extend other components with this sidebar component and do all the logic within this extended component (Will call it ExtendedComponent from now on).

Now while it comes to rendering, I do not store title and content via the parameters from above, I store them directly from within my ExtendedComponent. For the title, this is easy ofc since it’s just a string.

For the content, you might probably still like a partial, so I added this:

    public function onRender()
    {
        $this->content = $this->renderPartial('@default.htm');
        $this->dirName = "/my/plugin/components/sidebar";
    }

With this way, the ExtendedComponent renders the default.htm partial from the “/components/partials/extendedcomponent” folder and stores it within the content variable.

Then the dir name is changed to the plugin where the default component partial is and October search for the default.htm partial of the basic Sidebar Component and display title and content within the default partial as expected.

Worked out very well for me. Maybe it’s of use for others, too.

If there’re some errors within this solution, feel free to point them out ofc. ^^

This solution is great. The only downside I found with it is that you cannot override this shared partials from your theme.

Sorry for grave digging, but the latest October3.6 Update destroyed this solution and I cannot find the reason why.

I know there was some logic change around the partials, so maybe I could get a quick hint.

What’s happening:
Basically only the content is shown without the “surroundings” from the partial in the new dirName.
Any clue why?

Any help is welcome, thx a lot :slight_smile:

There haven’t been any changes to front end partials in v3.6 specifically, that I’m aware of. The partial changes were to form fields and list columns. I hope this helps.

1 Like

That is strange indeed. I updated and didnt think there are any changes for the frontend, too.

Was very surprised that I recognized that this broke. Gonna go on searching

Ok no idea what happened, but I could fix it with views.

Basically I how have a default component which is the frame for the sidebar block. Every component which extends that one call the parent::onRun() method which stores the regular component partial in a variable:

        $this->content = $this->renderPartial("@default.htm");

And also in the default sidebar component, I overwrite the onRender() method: Instead of rendering the partial, it should render a php view which basically use the store content to create the final sidebar block:

    public function onRender()
    {
        $this->viewPath = "plugins/my/plugin/views/";
        return $this->makeView("sidebarview.php");
    }

Just not sure if I did the viewPath / makeView() things setup correctly… but it works.