5
votes

I had a project in AEM 6.1's Classic UI where I was able to override the default Drag components or assets here label to a custom one simply like that:

  1. I've created a custom parsys component. Let's name it custom/parsys I've used sling:resourceSuperType to point to foundation/components/parsys.
  2. I've created custom/parsys/new respectively.
  3. I've overriden the new.jsp by adding these lines:

    String emptyText = currentStyle.get("cq:emptyText", ""); if (StringUtils.isNotBlank(emptyText)) { editConfig.setEmpty(true); editConfig.setEmptyText(emptyText); }

Now I was able to easily customize each parsys' drop area label by setting it via /etc/designs/custom structures. So every parsys was basically explicitely telling the author what kind of components it accepted. Apart from the traditional components' availability inside parsys this added a great value for the editors to work with a complex structure of a page with many different paragraphs, often nested one in another.

Now I'm working in AEM 6.3 with Touch UI and a lot has changed in a way that does not allow me to simply port the above solution. Googling the issue did not help unfortunately, 6.3 is quite fresh, there are solutions for older versions of wcm/foundation/components/parsys and/or foundation/components/parsys, but not for the latest one. Has anyone worked this one out already?



UPDATE: I've created a sample project with the Classic UI solution. So here we have the new.jsp and corresponding configuration under designs. When built and deployed to AEM 6.3 it can be checked under /content/enigmatic and produces the desired behaviour: Screenshot of a customized parsys drop area
4
FWIW, TouchUI works on default rendition logic for empry state. So in author edit mode, your component should detect missing data and render an appropriate placeholder. Unfortunately this is no longer a jcr property and has to go in your HTL logic.Imran Saeed
I believe you've addressed an issue that is not related to my question unfortunately. As far as I understand your comment - handling an empty component is not a problem for me. I'd rather wish to find out how to customize the paragraph systems in Touch UI.reggie_7

4 Answers

3
votes

The above mentioned approaches will not work for Touch UI. Adobe has it hardcoded as "Drag Components Here" in their i18n file for the "new" section.

Alternative Solution: -

  • Find a way to overlay parsys.
  • Using selectors approach, modify its interaction with the Inspectable.js, where you can supply new component specific messages while including parsys, may be by using selectors For e.g.

<sly data-sly-resource="${@path='par1',resourceType='mysite/components/parsys',selectors='par-1'}"/>
  • Append the added selectors to the "new" section's classes within parsys.html, using

${request.requestPathInfo.selectors[0]}
  • Now, in the Inspectable JS you can do something like this, around line 102.

if (this.dom.hasClass("par-1")) {
  return "Customized Text for Par 1";
}
if (this.dom.hasClass("par-2")) {
  return "Customized Text for Par 2";
}
// New component placeholder
if (this.dom.hasClass(newComponentClass)) {
  return newComponentPlaceholderText;
}

For more details, refer:- Detailed Help text Customization For parsys in Touch UI

1
votes

AEM Parsys populates the Parsys drop text with CSS utilizing the data-text property on the placeholder element as you can see outlined in blue:

data-text property decides the parsys-drop-area-text

These are the default placeholder styles (of which we will override the content property with additional/custom CSS for our parsys component):

CQ Overlay Placeholder Styles

This is the custom/additional editor CSS on our component:

Additional CSS

This is the result:

success

P.S. : It is better to work with the data-path attribute for styling instead of the data-text attribute:

div[data-path='/content/aemarch13/home/jcr:content/NavbarNav/*']:before {
   content: 'Drop it here.'
}

Good Luck...

0
votes

By combining TechNiks' suggestion with my previous approach I've created a working solution. It's not perfect yet since it has to assume the paragraph resources are always in place. Additionally it creates many (probably redundant) request calls, but on the surface it works the way I wanted it to with simple configuration in designs and it proves it can be done. For optimization there's some more depper digging needed (that I will not do soon, that's why I post current version already). So these are the main steps I took:

  1. I use my own parsys overlay component,
  2. I supply it with config selector that grabs cq:emptyText from its design,
  3. I overlay Inspectable's function hasPlaceholder to request the configured value.

For details one can simply check the functioning code, the main commit being this one.

0
votes

I came accross the same feature request today, read your posts and came with much simpler solution:

1.Define in your component custom placeholder text using the cq:htmlTag configuration via the custom property data-placeholder-hint

<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
jcr:primaryType="nt:unstructured"
data-placeholder-hint="Drag and drop your fancy components here."/>

2.Overlay /libs/cq/gui/components/authoring/editors/clientlibs/core/js/model/Inspectable.js under /apps and replace the following lines of the function hasPlaceholder():

    if (this.dom.hasClass(newComponentClass)) {
        return newComponentPlaceholderText;
    }

with:

    if (this.dom.hasClass(newComponentClass)) {
        // START OVERLAY: custom parsys text hint
        // show custom text hint if set with the component's configuration cq:htmlTag via the property data-placeholder-hint
        var editableEl = this.dom.parents(".cq-Editable-dom[data-placeholder-hint],.cq-Editable-dom [data-placeholder-hint]").first();
        if(editableEl.length > 0) {
            var placeholderHint = editableEl.data('placeholderHint');
            var elClasses = this.dom.attr("class").split(" ");
            for(var i = 0; i < elClasses.length; i++) {
                var placeholderHintSelector = editableEl.data("placeholder-hint-" + elClasses[i]);
                if(placeholderHintSelector) {
                    placeholderHint = placeholderHintSelector;
                    break;
                }
            }
            if(placeholderHint) {
                return Granite.I18n.get(placeholderHint);
            }
        }
        // END OVERLAY: custom parsys text hint
        return newComponentPlaceholderText;
    }

3.If you have multiple parsys in your component and you want to show different placeholder for each of them, than use selectors to include those parsys components as described in the answer of @TechNiks, but continue to configure the placeholder hints as described in 1., just use the selector as suffix

<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0"
jcr:primaryType="nt:unstructured"
data-placeholder-hint="Drag and drop your fancy components here (default message)."
data-placeholder-hint-mypar1selector="Drag and drop your fancy components here (mypar1selector message)." />

What basically happens is that you set your placeholder message via the data attribute data-placeholder-hint and read it later from the JS if set, otherwise show the default one.

EDIT I edited my post in order to support multiple parsys placeholders as requested. It basically follows the same idea with the selectors as mentioned above, but uses my simplicity and flexibility for configuring and showing the messages without to hardcode messages in an overlay file.