Jump to content

How to autogenerate page name when add new page? Multiple templates.


Flashmaster82
 Share

Recommended Posts

I have a page with 5 different templates to choose from when adding a new page. I want to have individual default page names on every new pages that is added as child. I know the function "Name format children" but i only works if you have a single template file attached to the page. Or can i make a default name on each template instead? Hook?

Please help!

  • Like 1
Link to comment
Share on other sites

So my idea with this is like when you have added an customer page, then the customer wants a new service let say "Renovation" that we can add a new page choose the renovation template and it will autogenerate a new name. This is the optimal way i think because what name is other people that uses this gonna name it.. And also we have like smaller jobs like delivery so then its hard to make a new name that is easy to read if you have many jobs from the customer.

So the end result would look like this in the tree

  • (1234) Renovation June 25
  • (2343) Delivery Aug 8
  • (6532) Recycling May 6
  • (3533) Renovation Jan 16

 

Link to comment
Share on other sites

I’m still not 100% on our ultimate goal here. Do you really want to see the IDs in the tree?

If it’s just about the way pages look in the tree, you can configure that in the template settings. In the Advanced tab there is a setting called “List of fields to display in the admin Page List” that you could configure to something like ”({id}) {template.label} {date}“ to get pretty much what you’ve described. Depends on the default date output format that is set up in the date field. Obviously you can also just hardcode the template’s label instead of {template.label} since this is template-specific anyay. In any case, this technique is completely independent of the page’s title.

In fact, pages don’t need to have titles at all. You can uncheck “global” in the title field’s advanced settings and it will stop showing up in the Add screen. If these pages don’t need titles at all, because a combination of other values is sufficient, you can then remove the title field from the templates entirely. Or, if you want to keep it around because it can be a nice convention for all pages to have a title, you can make the field hidden for these templates, and generate pages’ titles on saving the page. The hook might look like this:

$this->addHookBefore("Pages::save(template=renovation|delivery|recycling)", function(HookEvent $event) {
    $page = $event->arguments(0);
    $page->of(false);
    $page->set('title', $page->template->label . ', ' . date('Y-m-d', $p->date));
});

If these pages are for internal use and don’t need a name (the bit that identifies the page in the url), you will spare users the need to make something up on the Page Add screen. Unfortunately I believe this is only possible if the parent page accepts only a single template for children. In that case you could go to Family tab of the parent page’s template settings and enter a “Name format for children”, pretty much like the page list fields above. The Page Add screen is then bypassed entirely, because ProcessWire knows everything it needs to know (parent, template, name).

I’m always in favour of skipping the Page Add business if possible, but in your case you need to choose a template anyway. To get rid of the name input, you might hook ProcessPageAdd::buildForm:

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
	//maybe check the parent page if you don’t want this to happen indiscriminately.
	//also, since you have multi-language inputs, you may have to adjust for that.

	//feels hackish, there may be a cleaner way to achieve this.
    $form = $event->return;
    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

	//ProcessWire won’t let you proceed without a name, so generate something here, or
	//just set a static value. PW will automatically make it unique by adding a number.
	//Be aware that it will increment any number at the end of the name if it’s not unique,
	//so if you add two pages with the name “2020-12-31”, the second one will end up as
	//“2021-12-32”. Also, you’ll get a warning, so it’s probably best to generate a unique
	//name yourself. At this point you can’t use the ID because it doesn’t exist yet, though.
    $nameField->value = 'schnitzelmedpommes';
});

The ability to have default page names with multiple possible templates may actully be a worthwhile feature to add to the ProcessWire core. I’m not sure why it wouldn’t work, and philosophically it would fit PW’s ideal to be a “Content Management Framework”. Not every page needs a deliberate name if it just stores data.

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

Hi again and thank you for that very detailed feedback ? My site is really complex so its hard to explain everything. I have a website for our company and also i´m working on a dashboard/invoice system that you also can view in password protected view on the site. I did uncheck the global settings for the title "worked" and also implemented your code in ready.php as you can see futher down. So now when i add new page i can choose a template and then it goes to the page "nice".

I also have a function in ready.php the third one as you can see that changes the title based on a few things. My problem now is that i have a repeater field in the template and when i add something to that and save an error displays, code below ready.php and also another thing in the last function in ready.php i want to display the label of the template but its not working ? maybe you can see whats wrong with everything, i´m not the best programmer. I didn´t change anything in your code except the namefield, dont know what to do with the _pw_page_name and InputfieldHidden. When i have the first function and the third function in ready.php it doesnt work with the repeater field? Also if possible i only want a couple of templates to bypass the add page stage. Thank you so much for the help so far btw.

 

<?php
$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {

    $form = $event->return;
    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

    $nameField->value = 'Newpage';
});




$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
   $page = $event->arguments(0);
    
   $geo = new \OpenCage\Geocoder\Geocoder('API-key');
    
   if ($page->matches('customer_project')) return;     
    
    $address_parents = $page->parent->address;        
        $addresss = $page->address; 

        $address_parent = str_replace( ' ', '%20', $address_parents) . ",";
        $address = str_replace(' ', '%20', $addresss) . ","; 

        $zip_parent = str_replace( ' ', '', $page->parent->zipcode);
        $zip = str_replace(' ', '', $page->zipcode);         

        $ort_parent = $page->parent->ort->title;        
        $ort = $page->ort->title;
  
     if ($page->customer_project_address === 0) {
       
     $result = $geo->geocode("{$address_parent}%20{$zip_parent}%20{$ort_parent}", ['language' => 'Sweden', 'countrycode' => '+46']);
     $first = $result['results'][0];
     $coordinates = $first['geometry']['lat'] . ',' . $first['geometry']['lng'];
     $page->setAndSave('mapping3', $coordinates); 
       }
    
     else if ($page->customer_project_address === 1) {
       
     $result = $geo->geocode("{$address}%20{$zip}%20{$ort}", ['language' => 'Sweden', 'countrycode' => '+46']);
     $first = $result['results'][0];
     $coordinates = $first['geometry']['lat'] . ',' . $first['geometry']['lng'];
     $page->setAndSave('mapping3', $coordinates); 
       }
    
});






$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
    $page = $event->arguments[0];
    if ($page->matches('dashboard_servicepage_totalrenovation|dashboard_service_bathroomrenovations|dashboard_service_extensions|dashboard_service_demolitions |dashboard_service_recyclings')) return; 
    $id = $page->id;
    
    if ($page->customer_project_address === 0) {
    $address = $page->parent->address;
    }
    else if ($page->customer_project_address === 1) {
    $address = $page->address;
    }
    
    $page->setAndSave('title', "($id) {$template->label} | $address");
});


?>

 

 

Fatal Error: Uncaught Error: Maximum function nesting level of '256' reached, aborting! in E:\Wamp\www\MyWebsite\wire\core\Page.php:1138

#0 E:\Wamp\www\MyWebsite\wire\core\Page.php(1138): is_int(false)
#1 E:\Wamp\www\MyWebsite\wire\modules\Fieldtype\FieldtypeRepeater\RepeaterPage.php(192): Page->get('templates_id')
#2 E:\Wamp\www\MyWebsite\wire\core\Page.php(1846): RepeaterPage->get('templates_id')
#3 E:\Wamp\www\MyWebsite\wire\core\PagesType.php(228): Page->__get('templates_id')
#4 E:\Wamp\www\MyWebsite\wire\core\Pages.php(1735): PagesType->hasValidTemplate(Object(RepeaterPage))
#5 E:\Wamp\www\MyWebsite\wire\core\Wire.php(397): Pages->___saveReady(Object(RepeaterPage))
#6 E:\Wamp\www\MyWebsite\wire\core\WireHooks.php(823): Wire->_callMethod('___saveReady', Array)
#7 E:\Wamp\www\MyWebsite\wire\core\Wire.php(465): WireHooks->runHooks(Object(Pages), 'saveReady', Array)
#8 E:\ (line 1138 of E:\Wamp\www\MyWebsite\wire\core\Page.php)

This error message was shown because: you are logged in as a Superuser. Error has been logged.

 

Link to comment
Share on other sites

Hi, I’m in bed but regarding maximum function nesting level, consider adding the noHooks option to your setAndSave call:

$page->setAndSave('title', "($id) {$template->label} | $address", ['noHooks' => true]);

I suspect you’re getting into an infinite loop because setAndSave triggers the hook on Pages::saved.

  • Thanks 1
Link to comment
Share on other sites

Ah, sorry, I could have noticed that yesterday, since it’s in the same line ? You’re using $template but haven’t defined a variable with that name. $page->template->label should work.

Btw, when you do this

   if ($page->matches('customer_project')) return;     

make sure to go to that page’s settings tab and check the “unique” box to prevent any other pages from getting the same name (theoretically possible in other parts of the page tree). Additionally you can probably make this faster by comparing $page->name directly. The matches() function first needs to parse the selector string and figure out what to do with it. Alternatively, test the entire path with $page->path or $page->url, that way you guarantee uniqueness.

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

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
 if ($page->matches('dashboard_servicepage_totalrenovation|dashboard_service_bathroomrenovation|dashboard_service_extension|dashboard_service_demolition|dashboard_service_recycling')) return;
    
    $form = $event->return;
  
    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

    $nameField->value = 'Newpage';
});

Hmm i got an error on this..

 

Fatal Error: Uncaught Error: Call to a member function matches() on null in E:\Wamp\www\MyWebsite\site\assets\cache\FileCompiler\site\ready.php:5

#0 E:\Wamp\www\MyWebsite\wire\core\WireHooks.php(915): ProcessWire->{closure}(Object(HookEvent))
#1 E:\Wamp\www\MyWebsite\wire\core\Wire.php(465): WireHooks->runHooks(Object(ProcessPageAdd), 'buildForm', Array)
#2 E:\Wamp\www\MyWebsite\wire\modules\Process\ProcessPageAdd\ProcessPageAdd.module(525): Wire->__call('buildForm', Array)
#3 E:\Wamp\www\MyWebsite\wire\core\Wire.php(394): ProcessPageAdd->___execute()
#4 E:\Wamp\www\MyWebsite\wire\core\WireHooks.php(823): Wire->_callMethod('___execute', Array)
#5 E:\Wamp\www\MyWebsite\wire\core\Wire.php(465): WireHooks->runHooks(Object(ProcessPageAdd), 'execute', Array)
#6 E:\Wamp\www\MyWebsite\wire\core\ProcessController.php(337): Wire->__call('execute', Array)
#7 E:\Wamp\www\MyWebsiteg\wir (line 5 of E:\Wamp\www\MyWebsite\site\assets\cache\FileCompiler\site\ready.php)

This error message was shown because: you are logged in as a Superuser. Error has been logged.

I only want to do this bypass on just these templates, when i add a new page elsewhere i get an error.

Link to comment
Share on other sites

The error happens because $page is not defined, so you can’t call matches() on it. Fixing it is slightly involved, because we’re hooking ProcessPageAdd::buildForm, which means you can’t just do $event->object->page.

$event is the HookEvent. It has information about the hook itself, the affected object and in this case the return value.
$event->object is the object whose method we’re hooking, i.e. ProcessPageAdd. ProcessPageAdd should know the parent page to which we’re about to add a child, but I’m not sure how best to access it.
$event->object->page is the page ProcessPageAdd belongs to. This will be a system page with the ID 6. It’s just “this is the Page Add Screen”, so that’s not what we need.

However, the form that PW has built contains a hidden field for the parent page which we can access: $event->return->getChildByName('parent_id'). This should contain the parent’s ID, but not the page object itself. So this might work:

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if ($parent->matches('dashboard_servicepage_totalrenovation|dashboard_service_bathroomrenovation|dashboard_service_extension|dashboard_service_demolition|dashboard_service_recycling'))
        return;

    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

    $nameField->value = 'Newpage';
});
  • Thanks 1
Link to comment
Share on other sites

My brain is exploding haha. Trying to understand everything.

Current code

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if ($parent->matches('dashboard_servicepage_totalrenovation|dashboard_servicepage_bathroomrenovation|dashboard_servicepage_extension|dashboard_servicepage_demolition|dashboard_servicepage_recycling'))
    return;

    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

    $nameField->value = 'Newpage';
});

It works when adding a page and everything but when i add a new page elsewhere there is no title or name field...

 

My parent template for the customer is "dashboard_customer" and the service templates children are

dashboard_servicepage_totalrenovation

dashboard_servicepage_bathroomrenovation

dashboard_servicepage_extension

dashboard_servicepage_demolition

dashboard_servicepage_recycling

 

also i did try to get the template label in the last function of ready.php but with no luck

$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
    $page = $event->arguments[0];
    
    if ($page->matches('dashboard_servicepage_totalrenovation|dashboard_servicepage_bathroomrenovations|dashboard_servicepage_extensions|dashboard_servicepage_demolitions|dashboard_servicepage_recyclings')) return; 
    $id = $page->id;
   
    
    if ($page->customer_project_address === 0) {
    $address = $page->parent->address;
    }
    else if ($page->customer_project_address === 1) {
    $address = $page->address;
    }
    
    $t = $templates->get("dashboard_servicepage_totalrenovation|dashboard_servicepage_bathroomrenovation|dashboard_servicepage_extension|dashboard_servicepage_demolition|dashboard_servicepage_recycling");
    $t->label;
    
    $page->setAndSave('title', "($id) $t $address", ['noHooks' => true]); 
    
});

 

Link to comment
Share on other sites

Right, so… We have a couple of different problems here. The template label thing is just a simple programming mistake. I’m sure you can figure it out by looking at the last three lines again.
Hints:
1. on $templates->get()
2. on API access in general (you can’t use $templates inside a function. This is an unfortunate ProcessWire quirk that makes things unnecessarily difficult for beginners. You just have to be aware of it OR simply use the functions API everywhere)

Now the ProcessPageAdd::buildForm hook. Let’s look again at what we’re hooking and what we want to accomplish.

Hooking after ProcessPageAdd::buildForm means that the hook code is being executed right after the Page Add Screen is generated. That is to say, the form that asks the user for the template they wish to instantiate under the given parent, if you will. This means that that code cannot know the user’s template selection. It can however know the parent page, i.e. the page of which the new page is going to be a child. So anything you do in the hook either happens in EVERY Page Add Screen, or you can make it depend on that parent page (which I called $parent in my example). It looks to me like you’re trying to skip the hook depending on the child template – this isn’t possible because that template has not been determined yet. If I understand the requirements right, you may want to do this:

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if ($parent->template->name === 'dashboard_customer')
    	return;

    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

    $nameField->value = 'Newpage';
});

Notice how I’m not using matching(). That function takes a selector string, so if you want to use it to test for a page’s template, you can probably do $page->matches('template=dashboard_customer'), but not $page->matches('dashboard_customer')!

Now, if you must make the default page name depend on the selected template and also want to hide the name field from users, you have several options:

  • Make the name field hidden the way we’ve been doing it and inject some Javascript to change its value whenever the selected template changes. Here you will still want to run the hooks only for some parent page where it makes sense. Adding the Javascript in ProcessPageAdd::buildForm could look like this:
    $form->appendMarkup .=
    	'<script>
            const templateSelect = document.getElementById("template");
            templateSelect.addEventListener("change", (e) => {
                const nameInput = document.getElementById("Inputfield__pw_page_name");
                nameInput.value = e.target.options[e.target.selectedIndex].innerHTML; //set the name to the selected template’s label
            });
            templateSelect.dispatchEvent(new Event("change")); //run the above function immediataly to capture the default value
        </script>';
  • Alternatively, hook ProcessPageAdd::processInput and determine the page name there. That’s the method that runs when you click „Save“ on the Page Add Screen, so at that point you’re committed to the selected template and parent. Still need to hook ProcessPageAdd::buildForm to make the name field disappear, though.

  • Thanks 1
Link to comment
Share on other sites

Thank you for the explanation. I got it working now!!

Current code

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
    
    $form = $event->return;    
  
    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);
  
	if (!$parent->matches('template=dashboard_customer'))
    return;
    
    $pageid = $page->id;
    $parentaddress->parent->address;
    
    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';

    $nameField->value = "($pageid) $parentaddress";
   
});

Only thing is that when i uncheck the Title global field, it won´t show up on the rest of the pages, only want to not show up at the specific templates. Don´t know how to fix that..

Link to comment
Share on other sites

Ok i think i fixed it now.

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {
    
    $form = $event->return;    
  
    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);
  
	if (!$parent->matches('template=dashboard_customer'))
    return;
    
    $pageid = $page->id;
    $template = basename($page->template->label,'.php');
  
    $nameField = $form->getChildByName('_pw_page_name');
    $nameField->wrapClass = 'InputfieldHidden';
    $nameField->value = "($pageid) $template";
    
    $titleField = $event->return;
    if(!$titleField->has('title')) return;
    $titleField->title->collapsed = Inputfield::collapsedHidden;
});

 

  • Like 1
Link to comment
Share on other sites

Umm yeah I mean did you run that code? From the looks of it I would say it should rain errors, but if it works for you, that’s great! Allow me to step through and critique it anyway:

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {

    //get the result of the hooked method, which is a form (class InputfieldForm).
    //it’s also the only form we care about here, so calling it $form is fine.
    $form = $event->return;

    //this gets the parent page, so we can stop doing anything unless we are
    //at the correct position in the page tree. good.
	//note the indent I added, though ;)
    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if (!$parent->matches('template=dashboard_customer'))
        return;

    /*this is going to error, because $page does not exist here. you CAN
     *call the current page by writing any of this instead of $page (you
     *don’t WANT to do that here, though. read on before you change this):
     * - page() (if you have functions API enabled in config.php)
     * - wire('page')
     * - $wire->page
     * - $this->page
     * - $this->wire('page')
     *see https://processwire.com/docs/start/api-access/
     *since this is confusing and for all other reasons stated in that link
     *i would recommend simply always using page() etc. */
    $pageid = $page->id;

    /*this is just weird and unnecessary unless your template labels contain
     *slashes and end in .php, which in itself seems weird and unnecessary?
     *if you want a template’s name (usually the same as the template file
     *without the extension), just use $template->name.
     * ===>  importantly, none of this makes sense because when this code runs, you  <===
     * ===>  cannot know the page’s id nor its template!!!                           <===
     * ===>  you want to give the page ITS OWN id for a name. this is impossible to  <===
     * ===>  know at this time, as the page has not been created yet. the template,  <===
     * ===>  likewise, has not been chosen by the user. this code BUILDS the drop    <===
     * ===>  down field that lets the user choose a template!                        <=== */
    $template = basename($page->template->label,'.php');

    //this was my suggestion to get the page name field from the form, however,
    //as we see below, you have discovered a better way, which is great!
    $nameField = $form->getChildByName('_pw_page_name');

    //this was my suggestion to make the field invisible. as you’ve discovered,
    //you could also use $nameField->collapsed = Inputfield::collapsedHidden.
    //there is a difference, though! AFAIK, Inputfield::collapsedHidden will
    //completely REMOVE the field from the form output, so you can’t change it
    //with javascript. that was my main reason to use the class instead,
    //because you may actually want to do that.
    $nameField->wrapClass = 'InputfieldHidden';

    //this shouldn’t work because of the $page business above. I guess it will
    //result in "() " because neither $pageid nor $template can have any
    //reasonable values.
    //moreover, you can’t use parentheses or spaces in page names, so they will
    //get stripped or converted to - anyway. remember this is the page name, not
    //the title.
    $nameField->value = "($pageid) $template";

    //this is unnecessary because we have already put $event->return into the
    //variable $form.
    $titleField = $event->return;

    //this is great, but you should remove the above line and use $form instead.
    if(!$titleField->has('title')) return;

    //this is a great way to get the title field from the form! also a great way
    //to get rid of it. it will still allow you to put a value inside at this point.
    $titleField->title->collapsed = Inputfield::collapsedHidden;
});

Now to do what you really want, you need to hide the fields you want to hide in this ProcessPageAdd::buildForm hook and use an additional hook to set the values. That second hook will have to run at some point when all the things you need to generate those values are known. Since you want to use the page id (there is no real reason to have the page id in the name that I can think of!), that point has to be AFTER the page has been saved. That’s fine, but if you contented yourself with just the template name + a number generated by PW, you could use the Javascript option I suggested above and obviate the second hook. It’s no biggie either way, so whatever. You could hook Pages::added, making your entire code look like this:

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {

    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if (!$parent->matches('template=idee'))
        return;

    //using the neater way to edit the field!
    $form->_pw_page_name->collapsed = Inputfield::collapsedHidden;
    $form->_pw_page_name->value = 'this is a temporary name nobody should ever see, just leave it';

    $form->title->collapsed = Inputfield::collapsedHidden;
    //no default value for the title
});

$this->addHookAfter('Pages::added', function(HookEvent $event) {

    //this time, we can get the page that has just been created!
    $page = $event->arguments(0);

    //same as above: only run under certain parents
    if (!$page->matches('parent.template=idee'))
        return;

    $page->setAndSave('name', "{$page->id}_{$page->template->name}");
});

 

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

Wow impressive reply thanks! Master class..

This is my current code

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {

    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if (!$parent->matches('template=dashboard_customer'))
        return;

    $form->_pw_page_name->collapsed = Inputfield::collapsedHidden;
    $form->_pw_page_name->value = 'Arbete';

    $form->title->collapsed = Inputfield::collapsedHidden;
});

$this->addHookAfter('Pages::added', function(HookEvent $event) {

    $page = $event->arguments(0);

    //same as above: only run under certain parents
    if (!$page->matches('parent.template=dashboard_customer'))
        return;
    
    $parent_address = $page->parent->address;
    $parent_ort = $page->parent->ort->title;

    $page->setAndSave('name', "{$page->id}_{$page->template->label}");
});

Also and i forgot to mention that i have another function below.

$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
    $page = $event->arguments[0];
    
     if (!$page->matches('template=dashboard_services_bathroomrenovations_servicepage|dashboard_services_demolitions_servicepage|dashboard_services_extensions_servicepage|dashboard_services_recyclings_servicepage|dashboard_services_totalrenovations_servicepage')) return; 
    
    $id = $page->id;
    
    if ($page->customer_project_address === 0) {
    $address = $page->parent->address;
    $ort = $page->parent->ort->title;
    }
    else if ($page->customer_project_address === 1) {
    $address = $page->address;
    $ort = $page->ort->title;
    }
    
    $template_label = $page->template->label;

    $page->setAndSave(
    'title', "($id) $template_label | $address, $ort"
    );
    
});

And now i when i add a new page this function overrides the title field. I also want that when adding a new page . I want to have the title field in the template as a title but the field itself is hidden and not editable. The id is important because this is an invoice system so the id is the invoice nr btw. So i do want the title to be populated when adding a new page just like the second function when saving. Maybe they are interfering with each other.. I guess your code only targeting the name field. Also when i use the second function i have to save the page twice to change the name field (url). hmm

Link to comment
Share on other sites

Update current code

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {

    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if (!$parent->matches('template=dashboard_customer'))
        return;

    $form->_pw_page_name->collapsed = Inputfield::collapsedHidden;
    $form->_pw_page_name->value = 'Arbete';

    $form->title->collapsed = Inputfield::collapsedHidden;
});

$this->addHookAfter('Pages::added', function(HookEvent $event) {

    $page = $event->arguments(0);

    //same as above: only run under certain parents
    if (!$page->matches('parent.template=dashboard_customer'))
        return;
    
    $page_id = $page->id;
    $label = $page->template->label;
    $parent_address = $page->parent->address;
    $parent_ort = $page->parent->ort->title;

    $page->setAndSave('name', "$page_id $label $parent_address $parent_ort");
});






$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
    $page = $event->arguments[0];
    
     if (!$page->matches('template=dashboard_services_bathroomrenovations_servicepage|dashboard_services_demolitions_servicepage|dashboard_services_extensions_servicepage|dashboard_services_recyclings_servicepage|dashboard_services_totalrenovations_servicepage')) return; 
    
    $id = $page->id;
    
    if ($page->customer_project_address === 0) {
    $address = $page->parent->address;
    $ort = $page->parent->ort->title;
    }
    else if ($page->customer_project_address === 1) {
    $address = $page->address;
    $ort = $page->ort->title;
    }   
    
    $template_label = $page->template->label;

    $page->setAndSave('title', "($id) $template_label | $address, $ort", ['noHooks' => true]);
    $page->setAndSave('name', "$id $template_label $address $ort", ['noHooks' => true]);
});

 

Link to comment
Share on other sites

Hi, have you achieved your desired results yet? Just a quick note: if you change multiple fields on one page it’s probably more efficient to just change them individually and then call $page->save() once, instead of using $page->setAndSave() multiple times. Read the docs for more info.

Also be aware you’re changing the page’s name every time (well, kind of) Address or Ort change. That can be desirable, but if the page is accessible at its default URL, that URL won’t be stable, and as everybody knows, cool URLs don’t change.

I’m not sure I completely understand your requirements, but it looks like it should kinda work? Obviously when you generate the page name in Pages:added and save it, the Pages::saved hook will be triggered and override that change, so you might want to run the first one with ['noHooks' => true] or just get rid of it.

 

  • Thanks 1
Link to comment
Share on other sites

$this->addHookAfter("ProcessPageAdd::buildForm", function(HookEvent $event) {

    $form = $event->return;

    $parentField = $form->getChildByName('parent_id');
    $parent = pages()->get($parentField->value);

	if (!$parent->matches('template=dashboard_customer_nonprofit_association|dashboard_customer_municipality_authority|dashboard_customer_housing_cooperative|dashboard_customer_company|dashboard_customer_client_contractor|dashboard_customer_private_person'))
        return;

    $form->_pw_page_name->collapsed = Inputfield::collapsedHidden;
    $form->_pw_page_name->value = 'Arbete';

    $form->title->collapsed = Inputfield::collapsedHidden;
});

$this->addHookAfter('Pages::added', function(HookEvent $event) {

    $page = $event->arguments(0);

    if (!$page->matches('parent.template=dashboard_customer_nonprofit_association|dashboard_customer_municipality_authority|dashboard_customer_housing_cooperative|dashboard_customer_company|dashboard_customer_client_contractor|dashboard_customer_private_person'))
        return;
    
    $page_id = $page->id;
    $label = $page->template->label;
    $parent_address = $page->parent->address;
    $parent_ort = $page->parent->ort->title;

    $page->setAndSave('title', "($page_id) $label | $parent_address, $parent_ort", ['noHooks' => true]);
    $page->setAndSave('name', "$page_id $label $parent_address $parent_ort", ['noHooks' => true]);
});





$wire->addHookAfter('Pages::saved', function(HookEvent $event) {
    $page = $event->arguments[0];
    
     if (!$page->matches('template=dashboard_services_bathroomrenovation_servicepage|dashboard_services_demolition_servicepage|dashboard_services_extension_servicepage|dashboard_services_recycling_servicepage|dashboard_services_totalrenovation_servicepage')) return; 
    
    $id = $page->id;
    
    if ($page->customer_project_address === 0) {
    $address = $page->parent->address;
    $ort = $page->parent->ort->title;
    }
    else if ($page->customer_project_address === 1) {
    $address = $page->address;
    $ort = $page->ort->title;
    }   
    
    $template_label = $page->template->label;

    $page->setAndSave('title', "($id) $template_label | $address, $ort", ['noHooks' => true]);
    $page->setAndSave('name', "$id $template_label $address $ort", ['noHooks' => true]);
});

Currrent code.

 

It works, only thing is that because i have multiple language i have to save twice to change the url.. And of course to many setandsave. I tried with this below but no luck..

$page->setAndSave([
        'title' => "($id) $template_label | $address, $ort",
        'name' => "$id $template_label $address $ort", ['noHooks' => true]
]);

 

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