Kirby tag to print modules

I am trying to make a custom tag that renders a specific module, set as a tag attribute (name).

(accordion: pagefaq name: faq)

and the tag…

<?php

kirbytext::$tags['accordion'] = array(
  'attr' => array(
    'name'
  ),
  'html' => function($tag) {
    $modulename  = $tag->attr('name');
    $modulerender = $page->moduleList()->find($modulename)->render($data = [], $return = false);
    return $modulerender;
  }
);

Unfourtunatly, it’s rendering out (accordion: pagefaq name: faq) in browser instead of parsing the tag. How do i debug a tag or figure out whats going wrong?

Ah ha! It didn’t like $page

This worked.

$modulerender = page()->moduleList()->find($modulename)->render($data = [], $return = false);

Although I have no idea what the difference is.

Now I have a new problem though. It doesn’t seem to work with invisible modules. I can’t make it visible because then it will show up at the bottom of the page with all the visible modules.

Cant see anything in the modules plugin docs about printing invisible modules. Is there a way to do this?

Get the page:

$tag->page()

Thanks, I got it to work, I just cant seem to get it to print an invisible module. :frowning:

The module methods filter by visible, so I guess this won’t work. Maybe you can use a workaround with tpl::load and the path to the module snippets, have never tested this.

Try to get the module without the moduleList()method.
Depending on your modules setup (subfolder or not) you can shorten the first part.

// Determine where the module pages live
if($childPage = $page->find(Kirby\Modules\Settings::parentUid())) {
  // Modules child page exists, use its children
  $modulePages = $childPage->children();
} else {
  // Try to use the direct subpages (filtered below)
  $modulePages = $this->page->children();
}

$module = $modulePages->find($modulename)->render($data = [], $return = true);

Well thats sounds like Chinese to me. :slight_smile:

Perhaps another way will suffice - filter out this specific module template from <?php $page->modules() ?> instead of working with invisible. Maybe theres a way to do that…

Awesome! Thanks a lot. That worked, with some tweaks…

<?php

kirbytext::$tags['accordion'] = array(
  'attr' => array(
    'name'
  ),
  'html' => function($tag) {

    $modulename = $tag->attr('name');
    $modulePages = $tag->page()->find('modules')->children()->invisible();
    $modulerender = $modulePages->find($modulename)->render($data = [], $return = false);

    return $modulerender;
  }
);

Hmm… Its working, except its rendering at the top of the page, instead of where i want it in the body of text. The markdown is getting rendered underneath.

What could cause that?

Could be because the modules are not wrapped within a wrapping div?

Thats not that, i checked. its not the styling. The html is getting generated in the wrong order.

The heading that is above to Kirby tag is getting rendered under the custom tag, instead of above it.

What does the module look like?

HTML:

<div class="accordion-wrap">
<div class="accordion">
<?php foreach($module->accordion()->toStructure()->sortBy('header')->flip() as $acc): ?>
	<div>
		<h2><?= $acc->header()->html() ?></h2>
		<div class="acc-panel"><?= $acc->text()->kirbytext() ?></div>
	</div>
	<?php endforeach ?>
</div>
</div>

Blueprint:

title:               Accordion
pages:               false
files:               false

fields:
  accordionheadline:
    label:           Accordion
    type:            headline
  title:
    label:           Title
    type:            text
  accordion:
    label:           Accordion Content
    type:            structure
    entry:           >
      {{header}}
    fields:
      header:
        label:       Header
        type:        text
      text:
        label:       Text
        type:        simplemde

I think return must be set to true:

$modulerender = $modulePages->find($modulename)->render($data = [], true);

You are passing the stuff to a variable…

WohoOoo! that did it. Thanks.

It’s Chinese takeaway time… :chopsticks: