Jump to content

delegated template approach render method


jploch
 Share

Recommended Posts

Hey folks,

I have a question regarding rendering of template files that are in a subfolder of the template folder.
How would I for example render these PageTable items, when their template files are inside templates/blocks/:

 <div class="grid">
    <?php foreach($page->grid_ext as $item): ?>
    <div id="pteg_<?= $item->id ?>">
      <?php echo $item->render(); ?>
    </div>
    <?php endforeach; ?>
  </div>

I tried this, but get an error:

<?php echo $item->render(wire('config')->paths->templates . '/blocks/'); ?>

 

Link to comment
Share on other sites

this is working:

<?php echo $item->render($config->paths->templates . "blocks/" .$item->template->name. ".php"); ?>

It would be better if I could get the folder of the PageTable settings (the settings where you can specify an alternative folder for your templates) programmatically

Link to comment
Share on other sites

2 hours ago, jploch said:

It would be better if I could get the folder of the PageTable settings (the settings where you can specify an alternative folder for your templates) programmatically

I mean, you could do something like this:

//in site/ready.php
$this->addHook("Page::renderBlock", function($event)
{
    $page = $event->object;

    if ($page->template->altFilename)
        $blockPath = $page->template->altFilename;
    else
        $blockPath = $page->template->name;

    $blockPath = "blocks/{$blockPath}.{$this->wire('config')->templateExtension}";

    $event->return = $page->render($blockPath, $event->arguments(0));
});

Now you can call $page->renderBlock() or $page->renderBlock(['this' => 'that']) and the block’s template path will be determined automatically according to the template settings.

Or this, maybe:

$this->addHook("Page::renderBlock", function($event)
{
    $page = $event->object;

    $templatePath = $this->wire('config')->paths->templates;
    $templatePath = substr_replace($page->template->filename, 'blocks/', strlen($templatePath), 0);

    $event->return = $page->render($templatePath, $event->arguments(0));
});

 

  • Like 2
Link to comment
Share on other sites

1 hour ago, psy said:

@jploch Does this help? On the Template -> Edit -> Files tab, you could nominate an alternative template/path for your PageTable template.

1752310061_Screenshot2020-07-1022_22_58.thumb.png.f4fb49a80602a579b2a2661d4aa213c0.png

I can't set a path this way. I think this defines only the name of the template, if I input the path it gets removed after page save.

Link to comment
Share on other sites

36 minutes ago, Jan Romero said:

Or this, maybe:


$this->addHook("Page::renderBlock", function($event)
{
    $page = $event->object;

    $templatePath = $this->wire('config')->paths->templates;
    $templatePath = substr_replace($page->template->filename, 'blocks/', strlen($templatePath), 0);

    $event->return = $page->render($templatePath, $event->arguments(0));
});

Thank you! This looks promising, as I could make the folder name dynamic (it's for a module based on pagetable).
However this throws me an error (Method Page::renderBlock does not exist or is not callable in this context) on the frontend and also the page tree in the backend stops working after I insert that hook inside my module inside public function ready() 

Link to comment
Share on other sites

On 7/10/2020 at 12:29 PM, jploch said:

Hey folks,

I have a question regarding rendering of template files that are in a subfolder of the template folder.
How would I for example render these PageTable items, when their template files are inside templates/blocks/:


 <div class="grid">
    <?php foreach($page->grid_ext as $item): ?>
    <div id="pteg_<?= $item->id ?>">
      <?php echo $item->render(); ?>
    </div>
    <?php endforeach; ?>
  </div>

 

I would go this way, without invoking ready.php or other resources:

 <div class="grid">
    <?php foreach($page->grid_ext as $item): ?>
    <div id="pteg_<?= $item->id ?>">
      <?php 
		// specify the template viewfilename like this, if it is a single viewfile:
        $viewFilename = $wire('config')->paths->templates . 'blocks/myblockviewfile.php';
         
		// or if you have different files get them from template properties:
  		$viewFilename = $item->template->altFilename ? $item->template->altFilename : $item->template->name;
        $viewFilename = $wire('config')->paths->templates . 'blocks/' . $viewFilename . '.' . $wire('config')->templateExtension;
        
        // check if viewfile is available
        if(!is_readable($viewFilename)) {
            echo logSectionError('Missing Template-View-File!', '<strong>' . basename($viewFilename) . '</strong>');
            continue;
        }
         
        // now pack a bag with all needed variables for the block render template file:
        $viewBag = [];
        $viewBag['item'] = $item;
        $viewBag['page'] = $item;     // if you use the $page var in your template file, pass here the current item-page to it !
        $viewBag['pages'] = $pages;   // optionally if you need other vars, add them here
        $viewBag['config'] = $config; //  "
        
        // and render the block
		echo "\n      "  . wireRenderFile($viewFilename, $viewBag);

      ?>
    </div>
    <?php endforeach; ?>
  </div>

https://processwire.com/api/ref/functions/wire-render-file/

 

Edited by horst
added a check for viewfile existence
  • Like 2
Link to comment
Share on other sites

  • 3 months later...

the rendering works fine now with this in my template files:

<div class="grid">
    <?php foreach($page->grid_ext as $item): ?>
    <div id="pteg_<?= $item->id ?>">
      <?php echo $item->render($config->paths->templates . "blocks/" .$item->template->name. ".php"); ?>
    </div>
    <?php endforeach; ?>
  </div>

However the PageTable who renders the items in admin still throws an error, that the file is not found. 

TemplateFile: Filename doesn't exist: /Users/janploch/sites/michael-bader/dist/site/templates/block_icon.php

Since Iam extending PageTable with my own module i have this in my module to render the items (based on PageTableExtended, extending render methode  ___renderTable, shortened code)

foreach ($pagesToRender as $p) {
            

            $layoutTitle = $p->template->label ? $p->template->label : $p->template->name;
            $ext = "." . $this->config->templateExtension;
            $template_name = $p->template->altFilename ? basename($p->template->altFilename, $ext) : $p->template->name;
            $templateFilename = $this->config->paths->templates . $this->pathToTemplates . $template_name . $ext;
          
            $parsedTemplate = new TemplateFile($templateFilename);
            $parsedTemplate->set("page", $p);
            $parsedTemplate->set("isAdmin", 1);
            $parsedTemplate->options = array('pageGrid' => true);
          
          $p->template->filename = $this->config->paths->templates . "blocks/" .$p->template->name. ".php";

            $p->of(true);

            $iconClass = "fa-angle-down";
            $activeClass = "pte-open";
            $statusClass = "";

            if ($p->is(Page::statusUnpublished))
                $statusClass .= " pte-unpublished";
            if ($p->is(Page::statusHidden))
                $statusClass .= " pte-hidden";
            if ($p->is(Page::statusLocked))
                $statusClass .= " pte-locked";

            if ($this->collapseUnpublished && $p->is(Page::statusUnpublished)) {
                $iconClass = "fa-angle-right";
                $activeClass = "hiddenOnStart";
            }
          
          // add class for permisssions
          if(!($this->user->hasPermission('page-edit', $p))) {
            $statusClass .= " pte-locked"; 
          }
          
          if($this->user->hasPermission('pagegrid-drag')) { 
              $statusClass .= " pgrid-item-draggable"; 
          }
          
          if($this->user->hasPermission('pagegrid-resize')) { 
              $statusClass .= " pgrid-item-resizable"; 
          }
          
                //if ($p->colorpicker && $p->colorpicker!='transparent') $colorstr=' style="background-color:'.$p->colorpicker.'"'; else $colorstr='';
                $layout .= '<div id="' . $this->sanitizer->attrName($p->title) . '" data-id="' . $p->id . '" class="'. $this->sanitizer->attrName($p->title) .' pgrid-item-' . $p->id . ' pgrid-item ' . $p->template->name . $statusClass . '" data-template="' . $p->template->id . '">
	        <div class="pgrid-item-header"><span title="'.$this->_('Move').'" class="renderedLayoutTitle ' . $activeClass . '">' . $layoutTitle . '</span>
	        <input class="focusdummy" id="focusdummy' . $p->id . '" type="text">
                <a class="InputfieldPageTableSave" title="'.$this->_('Save Text').'" data-id="' . $p->id . '" href="#"><i class="fa fa-save"></i></a> 	        						
		<a class="InputfieldPageTableEdit" title="'.$this->_('Edit').'" data-url="./?id=' . $p->id . '&modal=1" href="#"><i class="fa fa-pencil-square"></i></a> 
	        <a class="InputfieldPageTableDelete" title="'.$this->_('Mark for deletion').'" href="#"><i class="fa fa-window-close"></i></a>
	        </div>' . $parsedTemplate->render() . $imageUpload . '</div>';
            
        }

I don't understand why the render method still throws the exeption that the file is not found.
When I put this in my template file for the items:

<!--Supress render warning-->
<?php $page->template->filename = $config->paths->templates . "blocks/" .$page->template->name. ".php"; ?>

the warning disappears. It would be great if the user of my module do not have to put this in every template file, when using the delegate template approach. Any Ideas how to solve this?

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...