Changing a blueprint on the fly when creating a subpage

Hi community,
according to the discussion from Allow users to change field label and calling field label in template:
I’d like to have different labels for some fields in different pages that all share the same blueprint. The mentioned article showed me how to access the blueprint elements correctly. I’m trying to get this to work in a page.create:after hook as follows (abrigdged for clarity):

return [
    "hooks" => [
        "page.create:after" => function ($page) {
            if (Str::endswith(($parent = $page->parent()->blueprint())->name(), "overview")) {
                $page->blueprint()->field("subpageshead")["label"] = "Special subpages";
            }
        },
    ],
];

In a real world example, the string "Special subpages" would be replaced by some smart function evaluating the desired label from both $parent and $page.
So far I had no luck with this approach. The label initally present in the overview blueprint remains stuck to the field subpages in the blueprint of my new subpage.
How can I make this work? Another event to hook on (perhaps page.create:before)? Where can I find an explanation in the docs?

Short answer: You can’t (at least not like this).

$page->blueprint() reads the blueprint and returns the values defined there. You cannot, however, change these values unless you would actually parse the blueprint, make your changes and save the changed values back to the blueprint file. But then you would end up with the same result, i.e. the same label for all pages that use the blueprint.

Having said that, you can use query language to change the label based on some condition via a custom method as explained here: Allow users to change field label and calling field label in template - #5 by texnixe (but instead of querying some field, you would use a method that returns the desired value).

1 Like

Thank you for pointing out a possible solution; having multiple blueprints that differ only by a handful of labels would not by especially DRY. :slightly_smiling_face:

I thought of that myself, but I have no clue where to put the code for such a custom method and how to make the blueprint query find that.

That would go into a plugin:

Or, if it is related to a particular page type, the a model would work well:

You would then for example create a page method label, which would return the desired value and use that in your blueprint.

1 Like

Thanks again. I have already a page model for my overview page. I’ll try that, hopefully figuring out the required blueprint query syntax. I think that must go along the line

sections:
  subpageshead:
    type: fields
    fields:
      subpageshead:
        label: "{{ page.label('subpageshead') }}"
        type: headline

I’ll come back to report success or failure.

Many thanks to @pixelijn and all other contributors of this very helpful community. The suggested solution works like a charm.

1 Like