Jump to content
jploch

delegated template approach render method

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/'); ?>

 

Share this post


Link to post
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

Share this post


Link to post
Share on other sites

@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

  • Like 1

Share this post


Link to post
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 1

Share this post


Link to post
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.

Share this post


Link to post
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() 

Share this post


Link to post
Share on other sites

Mh, it works for me. I believe 'autoload' => true must be set for it to call ready(). Have you tried reinstalling the module?

Share this post


Link to post
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 1

Share this post


Link to post
Share on other sites

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?

Share this post


Link to post
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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By LAPS
      I opened a new wishlist topic on the PW forum for this and in the meantime I ask to the community looking for a reasonable solution.
       
      Using the PageTable field, is there a way to un-restrict the creation of pages under a given parent template page (or as page children if no parent for items is selected)? That is, is there a way to allow the selection of the parent page dynamically / on the fly during page creation via the PageTable field?
    • By LAPS
      I'm using the PW PageTable field extensively and I think an improvement to it could be made regarding the ability to choose the page parent where the page created via PageTable will reside.
      Say you have a PageTable field set like this:
      Edit Field: page_table_field > Details >
      Select one or more templates for items
      > template_one
      > template_two
      > template_three
      Select a parent for items
      > parent_template
      Actually, you can only create pages under the parent_template page (or as page child if no parent for items is selected).
      BTW I am looking for reasons about this limitation.
      What about allowing to choose on the fly where the pages created via PageTable will reside? that is, having the possibility to choose dynamically under which parent page to create the pages?
      Actually, one could overcome to this by creating multiple appropriately set PageTable fields, one PageTable field per PageTable parent for items, but this is unsustainable (?) when you want to create a lot using PageTable…
      By allowing to choose dynamically / on the fly the parent page during page creation via the PageTable field would open up a wider usage of PageTable.
      What do you think about?
       
      @ryan @Robin S
    • By louisstephens
      So I ran into a very strange issue today. I have a template with a pagetable and I went to add an item to it, when I went to select an image (for an image field) the page instantly threw up an error
      "ProcessPageSearchLive: No search specified"
      The page's content also switched to the image attached. This all worked perfectly last week (local mamp box). Has anyone experienced this before, and how did you solve it?
       

    • By christophengelmayer
      Hi everyone,
      I'm working on a CLI script that renders paginated pages.
      Therefore I iterate trough paginated pages and set the page number and render the result.
      My problem is, after calling the render function for the first time, the output doesn't change even if I change the page number.
       
      DEMO:
      I'm using a template that renders a pagination of its children:
      <?php echo $page->children("limit=3")->render(); ?> I can view the paginated results in the Browser:
      /page-rendering-pagination/ /page-rendering-pagination/page2 /page-rendering-pagination/page3 ... When trying to render the different pages using the API I always get the first result, even if I change the page Number.
      <?php namespace ProcessWire; include('./index.php'); wire('input')->setPageNum(1); $p = wire('pages')->get('/page-rendering-pagination'); var_dump($p->render()); // renders first three items wire('input')->setPageNum(2); var_dump($p->render()); // also renders the first three items Am I missing something? Is there some kind of caching mechanism that I'm not aware of?
      Thanks for your help.
    • By tron1000
      Hello! I use PW 3.0.98 and I have frontend editing enabled for a PageTable Field. Somehow, when I double click the field in the frontend, the iframe in wich the content is displayed is very small (see screenshot). I couldn't find out if thats some CSS conflict or another problem. Any suggestions? Thanks, Andrej
       

×
×
  • Create New...