1
votes

I am dependent on getting a json-structure (or something similar) from an AEM cq-dialog to the DOM of the rendered page, where i pick it up by the rendered page's JS.

The sightly page template looks something like the below, here the data-labels are a json-containing the fields of the dialog. As you see I have manually typed all fields/properties:

<div id="myApp"
     data-service="${properties.applicationService}"
     data-labels="{&quot;title&quot;:&quot;${properties.title}&quot;,&quot;sub1&quot;:&quot;${properties.sub1}&quot;,&quot;number&quot;:&quot;${properties.number}&quot;}"></div>

I rather like to be able to pick up all labels more dynamically: data-labels = ${properties.labels}

Can I get all the "label" properties from the cq-dialog to the template as one property?

My dialog has a couple of fields like below, all the properties on tab1 are considered "label" properties (and hence should be added to the #myApp element's data-labels attribute).

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
          jcr:primaryType="cq:Dialog"
          title="my Application"
          xtype="dialog">
    <items jcr:primaryType="cq:WidgetCollection">
        <tabs jcr:primaryType="cq:TabPanel">
            <items jcr:primaryType="cq:WidgetCollection">
                <tab1
                        jcr:primaryType="cq:Widget"
                        title="Texts and Labels"
                        xtype="panel">
                    <items jcr:primaryType="cq:WidgetCollection">
                        <title
                                jcr:primaryType="cq:Widget"
                                fieldDescription="The title of the page."
                                fieldLabel="blablabla"
                                name="./title"
                                defaultValue="default value..."
                                xtype="textfield"/>
                        <sub1
                                jcr:primaryType="cq:Widget"
                                fieldDescription="First subtitle"
                                fieldLabel="blablba"
                                name="./subtitle1"
                                defaultValue="default value..."
                                xtype="textfield"/>
                        <number
                                jcr:primaryType="cq:Widget"
                                fieldDescription="The textfield label for number."
                                fieldLabel="number"
                                name="./number"
                                defaultValue="number"
                                xtype="textfield"/>
                    </items>
                </tab1>
...
1

1 Answers

2
votes

You could either write a custom ExtJs widget to store the data in the JCR as a JSON string or write a piece of backend (Java or JavaScript) code to read the properties and put them in a JSON object. Personally, I favour the latter approach.

Here's an example using Sling Models:

package com.mycompany.myproject.blah;

//imports, whatever

@Model(adaptables = Resource.class)
public class ItemsModel {

     // Properties will be injected by Sling Models from the current resource

     @Inject
     private String title;

     @Inject
     private String subtitle1;

     @Inject
     private String number;

     public String getJson() {
          // use String concatenation to build a JSON document
          // or create a JSON object using Gson or a similar library
          // and serailize it to String
     }
}

Then in your Sightly file, you can call the model

<div id="myApp" data-sly-use.model="com.mycompany.myproject.blah.ItemsModel"
     data-service="${properties.applicationService}"
     data-labels="${model.json}"></div>

If you don't want to or cannot use Sling Models, you could write a use class or use the JavaScript Use-API to achieve a similar result.

In your component folder, create a JS file, let's call it items.js, it could look like this:

"use strict";
use(function () {
    var items= {};
    items.title = "" + properties.get("title");
    items.sub1 = "" + properties.get("sub1");
    items.number = "" + properties.get("number");
    return JSON.stringify(items);
});

To use it in your Sightly script, call it via data-sly-use:

<div id="myApp" data-sly-use.items="items.js"
     data-service="${properties.applicationService}"
     data-labels="${items}"></div>

If you want to retrieve a number of properties in a more dynamic manner (without specifying each key in your Java/JS code), you can just iterate over all properties and filter them while building the JSON object.

Here's a somewhat crude example in JavaScript that reads all properties of the current resource and puts them in a JSON string:

"use strict";
use(function () {
    var result = {},
        i,
        keys,
        key;
    keys = properties.keySet().toArray();
    for (i = 0 ; i < keys.length ; i ++) {
        key = keys[i];
        result["" + key] = "" + properties.get(key);
    }
    return JSON.stringify(result);
});

I'm afraid there's no explicit documentation for the JavaScript API because you're effectively using the same APIs as you would in the Java code. Sorry about the weird type conversions but for some reason, stringify complained about the objects retrieved unless I did the trick with prepending an empty string to enforce the type "" + I tend not to use JS in my back-end code so I'm not very familiar with this particular style.

If you want to figure out what you can do with the properties object, take a look at the ValueMap javadoc