Jump to content

Add New - Set "Title" of new page with a select field combination (PageReference)


August
 Share

Recommended Posts

hello out there,

I created 2 text fields for first and last name. In line with this, PageReference fields were created in order to use it to create name combinations for page titles elsewhere.

How can I ensure that when creating a new page these two PageReference-fields are displayed directly on "AddPage" and my selection is saved as the title for this new page?

I read some stuff about Hooks and found snippets in these context, 

"$this->addHookAfter('Pages::added', function(HookEvent $event) {...};"
and
"$page->setAndSave( 'title', "($id) $template_label | $surname, $firstname" );"

But unfortunately I'm afraid I still have far too little experience with it.
So far I've only managed to hide the input for the title ..

image.png.ef4eb104a97da51bb58ece48d8ae59f0.png

It would be great to see how to include these 2 fields, select/addnew and save as pagetitle.

image.png.ccd6946e474837e3ffb02d6c5c39035c.png


Could someone please give me a hand so I can get a little further with my project?

Link to comment
Share on other sites

  • August changed the title to Add New - Set "Title" of new page with a select field combination (PageReference)
On 3/17/2022 at 9:47 AM, August said:

How can I ensure that when creating a new page these two PageReference-fields are displayed directly on "AddPage" and my selection is saved as the title for this new page?

I think a better way is to skip the Add Page step and then make sure the title is always automatically derived from your two fields when they are populated.

There are a few steps involved, illustrated here with case that is different to yours but you can see the similarity. In this example the template of the parent page that new pages are added under is named "creatures", and the child template (where the title is being set automatically) is named "creature".

1. For the "creatures" template, make sure that it allows a single template for children: the "creature" template.

2. For the "creatures" template, in the "Name format for children" setting enter "Y/m/d H:i:s". This will allow the "Add Page" step to be skipped and will automatically set the page name to the current date and time. We will later change the name in a hook.

2022-03-17_151444.thumb.png.82e78d6b717e1cc557ee507465c99cfd.png

3. Optional but recommended: for the "creature" template, choose the "creatures" template as "Allowed template(s) for parent". This lets you quickly add child pages via Pages > Add New and also ensures that new pages can't be added in the wrong place.

2022-03-17_151919.png.c5e596d45082a4fd1c02618c5ed4b450.png

4. For the "creature" template, edit the Title field in the template context and set the visibility to "Open when populated + Closed when blank + Locked (not editable)". The title is going to be set automatically so editors should not be able to change it manually.

2022-03-17_152450.png.72f8e8b29c493525b6b7d56b7315a213.png

5. Add hooks like the ones below to /site/ready.php.

// Pages::added
$pages->addHookAfter('added', function(HookEvent $event) {
	/** @var Page $page */
	$page = $event->arguments(0);

	// Creature
	if($page->template == 'creature') {
		// This is a newly added page so the fields that make up the title won't be populated yet
		$page->setAndSave('title', 'New creature');
	}
});

// Pages::saveReady
$pages->addHookAfter('saveReady', function(HookEvent $event) {
	/** @var Page $page */
	$page = $event->arguments(0);
	/** @var Pages $pages */
	$pages = $event->object;

	// Creature
	if($page->template == 'creature') {
		// Return early if the page is in the trash (thanks @taotoo)
		if($page->isTrash) return;
		// If the fields that make up the title are populated
		if($page->colour->id && $page->animal->id) {
			// Set the title
			$page->title = "{$page->colour->title} {$page->animal->title}";
			// Sanitize the title as a page name
			$name = $event->wire()->sanitizer->pageName($page->title, true);
			// Set the page name while making sure it auto-increments if there is a sibling page with the same title
			$page->name = $pages->names()->uniquePageName($name, $page);
		}
	}
});

 

Result:

creature2.gif.1abf54d056223b07dbbdfde1106af384.gif

  • Like 10
Link to comment
Share on other sites

Hi Robin S, thank you so much, thank you spending time on it - you saved my evening! 
Thats quiet nice, autocomplation works fine, too!
image.png.8223a206f93427f28ad0f5b8ffe39409.png

Now I would try to autoremove these autocreated pages, if you cancelling this action before you publish the page, because ...
Please have look: image.png.6f6068bc1e048b464e4ead4e514ea5c1.png

Do you think, a Hook like "pages()->addHookAfter('save', function(HookEvent $event) {...}" would be the right one here?
Beside the template I would check for a title, which is exactly the default-title "New Creature" (as in your great and helpful  example, shown above), then grabbing the id of this page, so that a deletion of these unessary page(s) is safe, using the Method "$pages ->delete(pages())"?

Link to comment
Share on other sites

1 hour ago, August said:

Do you think, a Hook like "pages()->addHookAfter('save', function(HookEvent $event) {...}" would be the right one here?

I don't think that will work because the page will also be saved immediately after it is created and so the hook would just delete it before it can be edited.

I suggest you just clean up abandoned pages on a regular shedule using LazyCron. First install the module at Modules > Install > LazyCron.

Then add a hook like this to /site/ready.php:

// Once per day
$wire->addHook('LazyCron::everyDay', function(HookEvent $event) {
	// Find pages that appear to be abandoned because they still have the default title 24 hours after creation
	$time = strtotime('-24 hours');
	$abandoned_pages = $event->wire()->pages->find("template=your_template, title='New Owner', created>$time, include=all");
	// Trash the abandoned pages
	foreach($abandoned_pages as $abandoned_page) {
		$abandoned_page->trash();
	}
});

You could delete the pages if you like but maybe safer to trash them and then just empty the trash once in a while.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...
On 3/16/2022 at 10:43 PM, Robin S said:

I think a better way is to skip the Add Page step and then make sure the title is always automatically derived from your two fields when they are populated.

@Robin S thank you highly. I learned so much from this. So wonderful and practical.

  • Like 1
Link to comment
Share on other sites

On 3/17/2022 at 9:43 AM, Robin S said:
// Pages::saveReady
$pages->addHookAfter('saveReady', function(HookEvent $event) {
	/** @var Page $page */
	$page = $event->arguments(0);
	/** @var Pages $pages */
	$pages = $event->object;

	// Creature
	if($page->template == 'creature') {
		// If the fields that make up the title are populated
		if($page->colour->id && $page->animal->id) {
			// Set the title
			$page->title = "{$page->colour->title} {$page->animal->title}";
			// Sanitize the title as a page name
			$name = $event->wire()->sanitizer->pageName($page->title, true);
			// Set the page name while making sure it auto-increments if there is a sibling page with the same title
			$page->name = $pages->names()->uniquePageName($name, $page);
		}
	}
});

 

Thank you for this code - it's very useful!

One thing I noticed is that when a relevant page is sent to trash, that page doesn't have the option to restore from trash. I think this might be because when pages go to trash they appear to be renamed by ProcessWire. Removing the final line (uniquePageName) seems to solve the issue, but you lose that functionality of course.

So based on a post of yours in another thread:

...I added an "isTrash" conditional, as below. Is this a reasonable solution or is there a better way?

	// Creature
	if($page->template == 'creature') {
		// Don't change name field if page is going to trash
		if(!$page->isTrash) {
            // If the fields that make up the title are populated
            if($page->colour->id && $page->animal->id) {
                // Set the title
                $page->title = "{$page->colour->title} {$page->animal->title}";
                // Sanitize the title as a page name
                $name = $event->wire()->sanitizer->pageName($page->title, true);
                // Set the page name while making sure it auto-increments if there is a sibling page with the same title
                $page->name = $pages->names()->uniquePageName($name, $page);
            }
		}
	}
});

 

  • Like 1
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

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...