April 26, 2020
Estimated Post Reading Time ~

AEM Touch UI issues

When working with AEM touch ui we often come across some issues. Below are some of the common issues which we face when using touch ui.
<cq:include path=’text’ resourceType=’foundation/components/text’/> 

In Sightly, you can do a similar one-liner:
<div data-sly-resource=”${‘text’ @resourceType=’foundation/components/text’}”></div>
However, there are a few things to be aware of when embedding components, especially when using Touch UI.
I will highlight three issues that I have come across when embedding components using Sightly and Touch UI, and explain the symptom, the cause, and give a solution for each.


ISSUE 1: Edit config does not refresh the page after component editThe Symptom
A component set up to refresh the page after edit does not refresh the page in Touch UI. In the web console there is a JavaScript error: Uncaught TypeError: Cannot read property ‘componentConfig’ of undefined.


The Cause
The component was in the .hidden component group. Touch UI has a list of editable, or components. This list does not include components in the .hidden group. When the component is edited, JavaScript runs that look for the component in the list of edibles. Because it is not on the list, the JavaScript throws an error and the editconfig afteredit action does not happen.
Uncaught TypeError: Cannot read property 'componentConfig' of undefined


The Solution
Put the component in a group other than .hidden. This will make the component available to be added to the list of components that can be dropped into a parsys, and it would be up to the content team to not include these components in the design configuration. To help keep this clear you could put the components into a group named Hidden.

Note: I am continuing to look for a good solution to handle components in the .hidden group since the parsys component is in that group and in my experience is the most common component to be embedded. So far I have not yet found a way to deal with this. It appears in Touch UI there is an update method that runs after closing the dialog, and that supersedes any custom afteredit event handlers attached to the component.

ISSUE 2: Dialog does not open in Touch UI
The Symptom
Embedded component’s dialog box doesn’t open in Touch UI. In the web console, there is a 400 (Bad Request) error.
The Cause
Embedded components do not create their content node until after the dialog has sent a POST to the component’s content path. The problem here is that in Touch UI the component looks for the dialog to open based on the content path. Since the content path doesn’t exist the dialog fails to open with an error.

The Solution
Make sure the content node for the component exists. There are a couple ways of doing this.

Add the component to the jcr:content of the template used to create the page.
Add a script to run just before the include of the component that creates the node if it doesn’t already exist. (Below is some example code For solution 2)
JS Use APIIn a file named EmbeddedComponent.js

"use strict";

/**
 * Creates a component node with name, if node does not yet exist.
 */
use([], function () {
    var newResourceName = this.name;
    var newResourceType = this.type;
    var resourceResolver = resource.getResourceResolver();
    var newNodePath = resource.path + "/" + newResourceName;
    var existingComponentResource = resourceResolver.getResource(newNodePath);
    if(existingComponentResource == null){
        var properties = {"jcr:primaryType":"nt:unstructured",
            "sling:resourceType":newResourceType};
        resourceResolver.create(resource, newResourceName, properties);
        resourceResolver.commit();
    }
});

Sightly script
<div data-sly-use="${EmbeddedComponent.js' @ name='primary', type='foundation/components/parsys'/> 
Java Use API
package com.aempodcast.example.components.utils;
import com.adobe.cq.sightly.WCMUse;
import java.util.HashMap;
import java.util.Map;
import org.apache.sling.api.resource.Resource;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.ResourceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class EmbedComponent extends WCMUse {
    private static final Logger log = LoggerFactory.getLogger(EmbedComponent.class);
    private ResourceResolver resourceResolver = null;
    private String resourceType = null;
    private String resourceName = null;
    private Resource resource = null;
    private Resource child = null;
    @Override
    public void activate() throws Exception {
        // Set resource Name and Type
        resourceName = get("name", String.class);
        resourceType = get("type", String.class);
        resource = getResource();
        child = resource.getChild(resourceName);
        resourceResolver = resource.getResourceResolver();
        
        if (child != null && !child.isResourceType(resourceType)) {
            updateResourceType();
        } else if(child == null) {
            createResource();
        }
    }
    private void createResource() {
        try {
            Map<String, Object> properties = new HashMap<>();
            properties.put("sling:resourceType", resourceType);
            resourceResolver.create(resource, resourceName, properties);
            commitChanges();
        } catch (PersistenceException ex) {
            log.error("Failed to create resource", ex);
        }
    }
    private void updateResourceType() {
        try {
            Node childNode = child.adaptTo(Node.class);
            childNode.setProperty("sling:resourceType", resourceType);
            commitChanges();
        } catch (RepositoryException ex) {
            log.error("Failed to update resource type", ex);
        }
    }
    private void commitChanges() {
        try {
            resourceResolver.commit();
        } catch (PersistenceException ex) {
            log.error("Failed to save changes", ex);
        }
    }
}

Sightly Script
<div data-sly-use="${com.aempodcast.example.components.utils.EmbedComponent'
@ name=’primary’, type='foundation/components/parsys'}" data-sly-resource="primary"></div>


ISSUE 3: Component select highlight goes beyond the component areas Symptom

Embedded component’s authoring highlight in Touch UI is bigger than the component itself, or an embedded component below is un-editable.

Each paragraph is a copy of a component. The topmost is embedded while the other four are dropped into parsys. The embedded component has a data-sly-unwrap set on it. The blue border shown is the selected topmost component. The other four components cannot be selected.

The Cause
The wrapping element of the component had been removed with data-sly-unwrap. Adobe Experience Manager puts a cq element, which holds helpful metadata for the authoring interface. One of the things it is used for is to set which element to use as the component boundary. When the component is selected, the boundary gets highlighted with a blue border. When the default wrapping element is removed, the next parent element is then used as the component boundary, which can cause the highlight to go beyond the component, and interfere with the ability to edit other components.

The Solution
Do not use data-sly-unwrap on elements including data-sly-resource.

Conclusion
In transitioning from CQ5 JSPs and the Classic UI to Adobe Experience Manager 6.0 Sightly and Touch UI, there are things that need to be adjusted in how they are done. Knowing the possible issues–and how to solve them–will make Sightly and Touch UI easier to use for developers and content authors.


By aem4beginner

No comments:

Post a Comment

If you have any doubts or questions, please let us know.