Skip to main content

acs.include: Parameterized Granite Dialog Include

Module README · Repository · Original ACS Commons Parameterized Include

acs.include lets a Granite UI dialog path-include a reusable field snippet and substitute ${{key:default}} placeholders via a parameters child node. It replaces ACS Commons' Parameterized Namespace Granite Include (acs-commons/granite/ui/components/include) and adds three opt-in capabilities: namespace cascading, conditional hide, and typed casting.

Authoring contract​

At the include site:

<caption
jcr:primaryType="nt:unstructured"
sling:resourceType="acs-include/granite/ui/components/include"
path="myapp/widgets/textarea/textarea">
<parameters
jcr:primaryType="nt:unstructured"
fieldLabel="Caption"
propertyName="./caption"/>
</caption>

path is a relative, search-path-style reference (/apps then /libs) -- no leading slash. The included snippet uses ${{key:default}} placeholders:

<textarea
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="${{fieldLabel:Text}}"
name="${{propertyName:./text}}"/>

If parameters supplies a key, that value is used; otherwise the literal text after : is used (or an empty string if there is no :).

When to use it​

Use acs.include when:

  • Several components share the same dialog field group (title + link, image crop options, CTA block) and you want one snippet to maintain.
  • You need per-include overrides for labels, property names, or defaults without copying XML.
  • You include the same snippet twice in one dialog and need namespaced name properties to avoid collisions.

Stick with a plain granite/ui/components/coral/foundation/include when the snippet has no parameters. Prefer copy-paste only for one-off dialogs that will never be reused.

Also covered on this site under Core Components dialog composition.

Opt-in: namespace cascading​

Include the same snippet more than once without colliding name / fileNameParameter / fileReferenceParameter values:

<block1
jcr:primaryType="nt:unstructured"
sling:resourceType="acs-include/granite/ui/components/include"
namespace="block1"
path="myapp/widgets/textwithlink/textWithLink"/>
<block2
jcr:primaryType="nt:unstructured"
sling:resourceType="acs-include/granite/ui/components/include"
namespace="block2"
path="myapp/widgets/textwithlink/textWithLink"/>

If the snippet stores ./text, block1 writes ./block1/text and block2 writes ./block2/text. Namespacing cascades into nested includes (ambient/own) but not into multifield rows -- multifield indexing already guarantees uniqueness.

Opt-in: conditional visibility (hide)​

Skip a (possibly nested) child of an included snippet based on a placeholder-resolved boolean:

<!-- inside the included snippet -->
<advancedOptions
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container"
hide="${{hideAdvanced:true}}">
<items jcr:primaryType="nt:unstructured">
<!-- ... -->
</items>
</advancedOptions>
<!-- at the include site -->
<caption
jcr:primaryType="nt:unstructured"
sling:resourceType="acs-include/granite/ui/components/include"
path="myapp/widgets/something/something">
<parameters
jcr:primaryType="nt:unstructured"
hideAdvanced="false"/>
</caption>

hide="true" after substitution skips that resource and its subtree. A hide on the snippet root skips the whole include.

Opt-in: typed casting​

Normalize substituted values to canonical Boolean / Long / Double string forms:

<properties
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs"
maximized="${{(Boolean)maximized:false}}"/>

With maximized="TRUE" in parameters, the (Boolean) hint canonicalizes the property to "true" instead of leaving the literal "TRUE". Unsupported parse results keep the original value rather than failing the include.

Building and deploying​

mvn clean install # build
mvn clean install -PautoInstallBundle # deploy core
mvn clean install -PautoInstallPackage # deploy ui.apps packages