Noel Boss

A hook to prefill PageTable fields with children on edit

Recommended Posts

Posted (edited)

I use a PageTable field to make edits to children of pages more intuitive

To register the hooks, insert the following Snippet inside your init function in your module (or add it to your init.php file):

/**
 * Initialize the module.
 *
 * ProcessWire calls this when the module is loaded. For 'autoload' modules, this will be called
 * when ProcessWire's API is ready. As a result, this is a good place to attach hooks.
 */
public function init()
{
	// Prefill pageTable field
	$this->wire()->addHookBefore('InputfieldPageTable::render', $this, 'addChildrenToPageTableFieldsHook');
	$this->wire()->addHookBefore('InputfieldPageTableAjax::checkAjax', $this, 'addChildrenToPageTableFieldsHook');
}

Then, add this hook method:

/**
 * Fill pagetable fields with children before editing….
 *
 * @param HookEvent $event
 */
public function addChildrenToPageTableFieldsHook(HookEvent $event)
{
	$field = $event->object;

	// on ajax, the first hook has no fieldname
	if (!$field->name) {
		return;
	}
	
	// get the edited backend page
	$editID = $this->wire('input')->get->int('id');
	if (!$editID && $this->wire('process') instanceof WirePageEditor) {
		$editID = $this->wire('process')->getPage()->id;
	}
	$page = wire('pages')->get($editID);
	
	// disable output formating – without this, the ajax request will not populate the field
	$page->of(false);
	
	// you could also insert a check to only do this with sepcific field names…
	// $page->set($field->name, $page->children('template=DesiredTemplate')); // just specific templates
	$page->set($field->name, $page->children);
}

Now whenever there is a page-table field on your page, it gets populated with the children

Edited by Noel Boss
Using $page->set() instead of ->add() removes "orphant message"
  • Like 5

Share this post


Link to post
Share on other sites

could you please mark this as [tutorial] or could an admin move it to the tutorials board? thx

  • Like 2

Share this post


Link to post
Share on other sites

@bernhard I felt my post is not qualified for a tutorial with »step-by-step instructions on how to do things in ProcessWire« – and since the description for API & Templates contains »answers and support on the API and template development« I thought it would better fit in there. I was actually looking for a hooks / snippet / recipe section in the forum – but that does not exists. I know, there is https://processwire-recipes.com but it just feels to cumbersome to add one 😉

  • Like 1

Share this post


Link to post
Share on other sites

OK i understand 🙂 I just didn't get that it was a snippet and "wasted" time to read your post and try to help where actually no problem existed and thought you might save others from that by naming it more obviously..

  • Like 1

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 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
       

    • By AndZyk
      Hello,
      I am not that experienced with hooks and was hoping if somebody could me with this task:
      I have a InputfieldFile in wich a single generated file will be added after checking a checkbox in the back-end and saving the page. This happens in the saveReady-hook of a page with a specific template inside a ready.php:
      <?php $this->addHookAfter("Pages::saveReady", function($event) { $page = $event->arguments(0); if ($page->template->name === "example") { if ($page->checkboxField) { $page->fileField->add($generatedFile); } } }); Now if a new file should be generated and there is already a file in this InputfieldFile, I would like to remove the previous file and replace it with the new one:
      <?php if (count($page->fileField)) { $page->fileField->removeAll(); } That works well so far. My problem is, that I want to add the new file with the same name filename.pdf. But when I remove the previous file and add the new file inside the same saveReady-hook, the previous file still exists until the page is saved and the name of the new file will be added a filename-1.pdf, because ProcessWire makes the filename unique when a file with the same name exists.
      My question is: Is there a hook or way to remove the previous file before the new file will be added to keep the same filename?
      I tried to unlink the previous file, but then the InputfieldFile doesn't always gets updated correctly and has one empty file and the new file. 😉
      Regards, Andreas
    • By dragan
      I'm trying to update certain repeater fields with a hook. This almost works, but is somehow buggy.
      Each repeater is supposed to represent a row: service, remarks, number of days, day-rate, row total.
      The last repeater should then show the grand total.
      I've tried this:
      $this->addHookAfter("Pages::saveReady", function (HookEvent $event) { $page = $event->object->getPage(); if ($page->template->id == 89 && $page->parent->parent->id == 11180) { $repeater = $page->offer_calc_repeater; $itemCount = $repeater->count(); $c = 0; $grandTotal = 0; foreach ($repeater as $rep) { if($c < ($itemCount - 1) ) { if (!empty($rep->days) && !empty($rep->daily_rate)) { $num_days = $rep->days; $day_rate = $rep->daily_rate; $row_total = $num_days * $day_rate; $rep->row_total = $row_total; $grandTotal = $grandTotal + $row_total; $page->save(); unset($num_days); unset($day_rate); unset($row_total); $c++; } } if ($c == $itemCount) { $rep->row_total = $grandTotal; } } } }); Most calculations are correct, but:
      The first one is empty.
      The second one is calculated wrong.
      I've tried typecasting (float), or checking with strlen instead of !empty, but that doesn't make any difference.
      Is the Pages::saveReady the ideal hook for such stuff? (placed in site/ready.php).
      Also, I get an error message: Session: Method Pages::getPage does not exist or is not callable in this context.
      Any ideas? Would you perhaps rather do stuff like this via JS?
    • By masslevel
      Hello!
      I apologize in advance if I missed something on the forums. I'm not yet that experienced with hooks and already tried a lot. Maybe someone else has an idea or could give me a hint in the right direction.
      In my ready.php file I'm creating a random generated URL slug on Pages::setupNew for a specific template. When creating a page and I type in the default language title and leave the other languages blank, the slug gets appended to the page names because the pages have the same url/slug/title but in different trees ( ex. /myarticle-myslug/ and /en/myarticle-myslug/ ) When creating a page and I enter a title for each language, the slug gets only applied to the default language and I get an error that the name for the default language already exists and it was changed to /myarticle-myslug/. The other language gets the page name /en/my-article/ applied. Additionally I noticed that the settings from Module -> Page Name (InputfieldPageName) are not applied when creating the page name using the code below. So non-ascii characters get stripped instead of sanitized Here is a simplified code snippet that I have in the ready.php file:
      wire()->addHookBefore('Pages::setupNew', function($event) { $page = $event->arguments('page'); if ($page->template->name == 'news-article') { $page->name = $page->title . '-myslug'; } }); I've read this topic and if this still applies, LanguageSupportPageNames isn't used on Pages::setupNew.  Especially the post by @Soma looks interesting but I'm not sure how to apply it.
      Thank you very much in advance.
    • By dragan
      $this->addHookBefore('InputfieldTextarea::render', function($event) { $field = $event->object; if($field->name == 'body_offer') { $del = ''; foreach($this->wire->pages->get(11229)->textblocks as $item) { $field->entityEncodeText = false; $body = str_replace(PHP_EOL, '', $item->body); $body = addslashes($body); $title = $item->title; $field->description .= $del . "<a href=\"#\" class=\"ckesnippet\" data-snippet=\"$body\">$title</a>"; $del = ' | '; } } $js = wire('config')->urls->templates . 'scripts/ckesnippets.js'; $event->return = str_replace("</html>", "\n<script type='text/javascript' src='$js'></script>\n</html>", $event->return); }); I'm trying to add custom text-blocks from repeater fields into CKEditor. I've stolen the whole idea (and code) from @bernhard

      Problem is: The links are actually being rendered, but the Javascript is not loaded, i.e. the $event->return line doesn't seem to work. If I inspect the HTML, my additional script-tag is nowhere to be seen. I don't get any errors either. Running latest PW dev + PHP 7.1.19.