AEM RichText Remove P Tag on Sightly

You may have been trying to search the internet for an out of box solution to remove the single paragraph container for Touch UI, and have found something like removeSingleParagraphContainer. But however, this attribute was for the Classic UI and deprecated. From my knowledge, there isn’t anything out of the box that can remove the p single paragraph container tag. However, I have spent some time and found a very lucrative solution. Lets remove the p tag from the rich text editor!

In this article, we will step through my implementation for us to remove the p tag once and for all, from being rendered.

My solution to this problem will be dealt with in the backend, Sling Model. Some may argue that the solution can be done using Javascript, but that can be very troublesome. Let’s Keep it Simple Stupid (KISS). There’s one caveat to this approach; scroll to the bottom of the page to see what it is.

Follow my 3 steps below to remove the P tag wrapper from what is being produced by the cq/gui/components/authoring/dialog/richtext.


Step 1. Add Custom Option In the Paraformat Options

Under the _cq_dialog.xml, cq/gui/components/authoring/dialog/richtext, add a new format option under the paraformat list of options.

The selected paraformat option will be a custom HTML element that wraps onto the highlighted or selected text from the author. In this case, when the author have selected text, and then click on the new paraformat option, the Html will look something like this <notextformat>sometext</notextformat>.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// new paraformt to be added into line:77
<notextformat
   jcr:primaryType="nt:unstructured"
   description="No - Text Format"
   tag="notextformat"/>











// the complete _cq_dialog.xml configuration for the cq/gui/components/authoring/dialog/richtext
// new paraformt to be added into line:77
<text
   jcr:primaryType="nt:unstructured"
   sling:resourceType="cq/gui/components/authoring/dialog/richtext"
   name="./text"
   useFixedInlineToolbar="{Boolean}true">
    <rtePlugins jcr:primaryType="nt:unstructured">
        <format
           jcr:primaryType="nt:unstructured"
           features="bold,italic"/>
        <justify
           jcr:primaryType="nt:unstructured"
           features="-"/>
        <links
           jcr:primaryType="nt:unstructured"
           features="modifylink,unlink"/>
        <lists
           jcr:primaryType="nt:unstructured"
           features="*"/>
        <paraformat
           jcr:primaryType="nt:unstructured"
           features="*">
            <formats jcr:primaryType="nt:unstructured">
                <default_p
                   jcr:primaryType="nt:unstructured"
                   description="Paragraph"
                   tag="p"/>
                <default_h1
                   jcr:primaryType="nt:unstructured"
                   description="Heading 1"
                   tag="h1"/>
                <default_h2
                   jcr:primaryType="nt:unstructured"
                   description="Heading 2"
                   tag="h2"/>
                <default_h3
                   jcr:primaryType="nt:unstructured"
                   description="Heading 3"
                   tag="h3"/>
                <default_h4
                   jcr:primaryType="nt:unstructured"
                   description="Heading 4"
                   tag="h4"/>
                <default_h5
                   jcr:primaryType="nt:unstructured"
                   description="Heading 5"
                   tag="h5"/>
                <default_h6
                   jcr:primaryType="nt:unstructured"
                   description="Heading 6"
                   tag="h6"/>
                <default_blockquote
                   jcr:primaryType="nt:unstructured"
                   description="Quote"
                   tag="blockquote"/>
                <default_pre
                   jcr:primaryType="nt:unstructured"
                   description="Preformatted"
                   tag="pre"/>
                <notextformat
                   jcr:primaryType="nt:unstructured"
                   description="No - Text Format"
                   tag="notextformat"/>
            </formats>
        </paraformat>
    </rtePlugins>
    <uiSettings jcr:primaryType="nt:unstructured">
        <cui jcr:primaryType="nt:unstructured">
            <inline
               jcr:primaryType="nt:unstructured"
               toolbar="[format#bold,format#italic,format#underline,#justify,#lists,links#modifylink,links#unlink,#paraformat]">
                <popovers jcr:primaryType="nt:unstructured">
                    <justify
                       jcr:primaryType="nt:unstructured"
                       items="[justify#justifyleft,justify#justifycenter,justify#justifyright]"
                       ref="justify"/>
                    <lists
                       jcr:primaryType="nt:unstructured"
                       items="[lists#unordered,lists#ordered,lists#outdent,lists#indent]"
                       ref="lists"/>
                    <paraformat
                       jcr:primaryType="nt:unstructured"
                       items="paraformat:getFormats:paraformat-pulldown"
                       ref="paraformat"/>
                </popovers>
            </inline>
        </cui>
    </uiSettings>
</text>

Step 2. Create the Backend, Sling Model, to Text Transform

The backend Sling Model will read the ./text property that has been set by the user’s input. Using the String.ReplaceAll(), we can replace all </?notextformat>, regex pattern, with nothing (meaning that this element will be removed).

For example <notextformat>sometext</notextformat>. -> sometext.

We next save the formatted text into a variable of , which can be used by sightly to display HTML on the page.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package com.sourcedcode.core.models;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.models.annotations.Default;
import org.apache.sling.models.annotations.Model;
import org.apache.sling.models.annotations.Optional;
import org.apache.sling.models.annotations.injectorspecific.ValueMapValue;

import javax.annotation.PostConstruct;

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

    @Optional
    @ValueMapValue
    @Default(values = "")
    private String text;

    private String richText;

    @PostConstruct
    protected void init() {
        if (!text.isEmpty()) {
            richText = text.replaceAll("</?notextformat>", "");
        }
    }

    public String getRichText() {
        return richText;
    }
}

Step 3. Render Text Transform from Sightly

Now finally we just need to utilise sightly to print the text transformed, richText, to the screen.

1
2
3
4
<sly data-sly-use.myTextComponent="com.sourcedcode.core.models.MyTextComponent"/>
${myTextComponent.richText @ context='html'}
<sly data-sly-use.templates="core/wcm/components/commons/v1/templates.html"
    data-sly-call="${templates.placeholder @ isEmpty = !myTextComponent.richText}"></sly>

Last Thoughts?
The caveat with this approach is that when you are trying to export JSON format from this component, you will be stuck with this block of text, <notextformat>sometext</notextformat>, unless if you text to transform the export as well.

The reason why I did not overwrite the JCR values is that I wanted to retain the natural editing experience for the authors. With my solution when the author decides to make changes to the rich text field, they would not have a werid experience.


Hello, I am an enthusiastic Adobe Community Advisor and a seasoned Lead AEM Developer. I am currently serving as an AEM Technical Lead at MNPDigital.ca, bringing over a decade of extensive web engineering experience and more than eight years of practical AEM experience to the table. My goal is to give back to the AEM Full Stack Development community by sharing my wealth of knowledge with others. You can connect with me on LinkedIn.

Leave a Reply

Your email address will not be published. Required fields are marked *


Back To Top