A Study in Dialog Data Types: Type Hints

05287_A-Study-in-Dialog-Data-Types_Type-Hints

Many Adobe Experience Manager authors and developers are familiar with the concept of a dialog box. In general, customizable AEM components give authors a set of options that they can author when they create or modify a component. The dialog box is the AEM mechanism by which developers enable authors to make these changes, usually without needing specific programming knowledge such as HTML, JavaScript, or CSS.

Dialog boxes, however, can be somewhat of a mystery for the unfamiliar developer, particularly when dealing with data types of the authored properties. How, for example, do I specify that a value of “true” from my dialog box dropdown should be stored as a Boolean instead of a String in the JCR? Or, how can I delete a property when the value passed to it is empty? These are questions that developers new to Adobe Experience Manager (like myself) naturally ask.

In order to solve this problem, we will first look at the technology running under the dialog box hood when we author its properties. Afterward, we will use the insights we gain to build dialog boxes that will appropriately handle our property data types.

The Mighty SlingPostServlet
An essential part of the Adobe Experience Manager architecture is the Apache Sling project, which provides (among other advantages) our RESTful framework for the resources stored in the underlying JCR. As a part of this framework, we have a servlet available to us called the SlingPostServlet, which we will shortly see endows us with powers to make changes to the JCR—assuming the necessary permissions, of course. :) The essential function of the SlingPostServlet is to create, modify, or delete nodes and their properties in a standard, RESTful way that can be utilized by different parts of AEM. This functionality is fairly well documented on the Sling website (https://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.html), but I will include a short example here for demonstration.

We will be sending a POST request to modify an existing jcr:content node on the Geometrixx Outdoors page, so pull up your favorite HTTP request client. I’ll be using cURL as my flavor of choice.

Assuming a default installation of AEM including the Sample Content (I’m using Adobe Experience Manager 6.0 Service Pack 2), navigate to /content/geometrixx-outdoors/en/seasonal/jcr:content using CRXDE, and look at this node’s properties under the “Properties” tab. You should see a “hideInNav” property of type “String” and a value of “true”:

blog-typehints--1

We will now construct a request that will hit the SlingPostServlet and change this String’s value to “false” by POSTing to the node we wish to modify. Here is the command that I will run from the terminal:

The name of the property, “hideInNav”, immediately follows the -F option, which instructs cURL to send the request as an RFC 2388 form submission. The “-u admin:admin” portion is the credential string needed to log in to my local instance, and the URL represents the location of the resource we wish to modify (specified above). Running this command appropriately modifies the “hideInNav” value to “false” as we can see below:

blog-typehints--2

(As an extra note, AEM also updates the “cq:lastModified” and “cq:lastModifiedBy” properties to match the time and credentials given for the submitted request).

The SlingPostServlet and AEM Dialog Boxes
Great, so now we can perform all these actions on the JCR. But what does that have to do with dialog boxes? The answer: once the dialog box is rendered by Adobe Experience Manager, its purpose is to construct a request to send to the SlingPostServlet, which will appropriately take care of CRUDing (https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) the component properties for us. Let’s go to our Seasonal page and see an example.

Open /content/geometrixx-outdoors/en/seasonal.html in edit mode (either in the classic or touch UI, but this blog post will focus on the touch UI) and pull up the page properties. Now open up your browser’s developer tools and clear all of the requests made in the network tab. Your screen should look something like this in Google Chrome:

blog-typehints--3

After making sure that your browser is recording your network activity, click the “Hide In Navigation” checkbox and save the dialog box. My page reloads when I edit the page, so I’ve set Chrome to preserve my log and filter out all but the XmlHttpRequest requests in my browser (since lots of calls are made to various HTML pages, images, resources, etc.), but you should see a POST request somewhere in the recorded network activity to /content/geometrixx-outdoors/en/seasonal/jcr:content (or _jcr_content) similar to the following:

blog-typehints--4

Click on the “_jcr_content” entry, the first entry on my screen, to see the request details. Here is the output on my machine:

blog-typehints--5

Viola! The dialog box constructed a POST request and submitted it to the Seasonal page’s jcr:content node as expected. Furthermore, if you look at the form data sent in our request you will see some variation of “./hideInNav: true” amongst the data, which sets our “hideInNav” property back to true as expected:

blog-typehints--6

Specifying Data Types with Type Hints
Now we FINALLY return to our JCR data types. We can leverage what we know about AEM’s dialog box functionality to correctly handle the data type of properties we want to manipulate, and we do so by using Sling Type Hints. Type hints are a way of telling the SlingPostServlet how we want to store a particular property in the JCR and are documented here (https://sling.apache.org/documentation/bundles/manipulating-content-the-slingpostservlet-servlets-post.html#typehint). The type hint lives as an additional node underneath the dialog directory. Its “name” property will generally look like this: @TypeHint, such as [email protected], and its “value” property: “”, such as “Boolean”. (To see all of the defined types, open the “Type” dropdown at the bottom of the CRXDE screen.)

As mentioned at the beginning of this post, sometimes we want our true/false values to be saved as Booleans instead of Strings. Let’s go back one more time to our example and attempt to achieve this with an Adobe Experience Manager component. There should be a simple component named “Title” at /apps/geometrixx-outdoors/components/title. Or, if there isn’t, you can grab the title component from the libs directory at /libs/foundation/components/title and copy that to the apps directory instead. Let’s add a Granite UI Select Component to the dialog box and call it “booleanField”. In CRXDE, create a new “nt:unstructured” node and give it the following properties:

blog-typehints--7

Now we will add the items to populate the dropdown. Create another new “nt:unstructured” node called “items”, and add two nodes beneath the “items” node called “true” and “false”. Here are the “true” option properties:

blog-typehints--8

The “false” properties are similar: enter “False Value” for the “text” property and “false” for the “value” property.

Now return to the Seasonal page and author a new “Title” component from the “General” category (this is the default category for the Geometrixx Title component) somewhere on the page. Open up the component’s dialog box and you should see something similar to this:

blog-typehints--9

We see our “Boolean Field Option” property as a dropdown at the bottom of the dialog properties. So far so good! Change the dropdown value and click the checkbox to save the changes. Now let’s go look at the properties of our new Boolean field:

blog-typehints-10

Whoops. You can see the “booleanField” property listed at the top of the properties list, and it has been given a String type. But not to worry—type hints to the rescue! Let’s add our Boolean type hint. Create another node in the dialog definition, “booleanFieldTypeHint”, of type “nt:unstructured” at the same level as “booleanField”. It will have the following properties:

blog-typehints--11

We can see the “name” property is [email protected] and the value is “Boolean”. It has a sling resource type of Granite UI “hidden”, which tells Adobe Experience Manager that it shouldn’t be visible to authors in the dialog box. The “ignoreData” property tells us that the “value” property of this node should always be “Boolean”, regardless of whatever value may find its way into the submitted form dialog under the name of “booleanFieldTypeHint”.

Now, delete the “booleanField” property from the title content node. (Note that this is the location of the specific title component authored on the Seasonal page, not the dialog box node! For example, on my machine, the path to my title content node is /content/geometrixx-outdoors/en/seasonal/jcr:content/sidebar/title_737116960.) Let’s try authoring the property again with our type hint in place. Open up the title dialog box and change our custom property value in the dropdown again. Here is the resulting request that my AEM instance sends when I save the changed dialog box:

blog-typehints--12

In the form data section we see our “./booleanField” value of “false” and a new property that matches the type hint we just created: “./booleanFieldTypeHint” with a value of “Boolean”, as expected. Now if we go back to CRXDE and look at the properties for our title component, there should be a change to the data type and the value of “booleanField”:

blog-typehints--13

As desired, our “booleanField” property at the top now has a “Type” value of “Boolean”! The JCR will now interpret this property as a Boolean instead of a String, as desired.

There’s lots more you can do with type hints. Make sure to check out the documentation and try using them in your own dialog boxes.

That’s it! As always, feel free to email us with any questions or comments to [email protected] Happy hinting!