Extend AEM Page Properties

Published
Page properties in AEM serve as metadata that provide essential information about a webpage. While AEM provides a standard set of properties to meet basic web project needs, organizations often enhance them with extra functionalities or custom data fields to effectively address more complex or unique requirements in content management.
We'll look at three ways in which we can extend page properties: adding new tab with text field, inserting new field into an existing tab, and hiding any tabs or fields that aren't relevant to the implementation.
We will be extending the page properties for AEM pages which uses Core Page Component. We need to follow the same node structure as the dialog in the page component to extend the page properties. According to the Proxy Component Pattern, we will only add or override the necessary properties. Here is the Page V3 component dialog structure:
page / _cq_dialog / .content.xml
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" jcr:primaryType="nt:unstructured" sling:resourceType="cq/gui/components/authoring/dialog"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <tabs jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/tabs"> <items jcr:primaryType="nt:unstructured"> </items> </tabs> </items> </content> </jcr:root>

Adding new Tab with Text Field

The child nodes of the items node represent tabs in the page properties. Let's incorporate Content Approval as a new tab. Typically, it's added at the end of the tab list, but you can adjust its position using sling:orderBefore orsling:orderAfter to place it before or after a designated tab, respectively.
page / _cq_dialog / .content.xml
<contentApproval jcr:primaryType="nt:unstructured" jcr:title="Content Approval" sling:orderBefore="cloudservices" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <approvalCode jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Approval Code" required="{Boolean}true" emptyText="Enter Content Approval Code" name="./approvalCode" maxlengthlong="{Long}12"/> </items> </column> </items> </contentApproval>

Inserting new Field within an Existing Tab

The Core Page component relies on the WCM foundation basic page component. To extend the dialog properties of any tab, it's essential to inherit that specific tab from the foundation basic page component dialog using sling:resourceSuperType otherwise, all existing properties will be replaced with the new ones.
page / _cq_dialog / .content.xml
<basic jcr:primaryType="nt:unstructured" sling:resourceSuperType="wcm/foundation/components/basicpage/v1/basicpage/tabs/basic" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <title jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/fieldset"> <items jcr:primaryType="nt:unstructured"> <hideSubPagesInNav jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/checkbox" name="./hideSubPagesInNav" renderReadOnly="{Boolean}true" text="Hide all subpage in Navigation"/> </items> </title> </items> </column> </items> </basic>

Hiding Existing Tabs or Fields

Hiding tabs and fields can be achieved by either using sling:hideChildren to list all the items to be hidden in the parent items node, or setting sling:hideResource to true in the specific node that needs to be hidden.
page / _cq_dialog / .content.xml
<tabs jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/tabs"> <items jcr:primaryType="nt:unstructured" sling:hideChildren="[personalization,cloudservices]"> <thumbnail jcr:primaryType="nt:unstructured" sling:hideResource="{Boolean}true"/> </items> </tabs>