Event handler for delete child component in AEM/CQ - aem

How can I add an event handler for my Adobe AEM6 component that triggers when a child component is deleted?
There are several listeners that I can attach event handlers to, listed in the documentation for cq:listeners but unfortunately there isn't one for afterchilddelete.
I've tried adding a cq:childEditConfig node to the component but, at least in AEM6, the handler doesn't fire:
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:EditConfig">
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
afterdelete="mynamespace.afterchilddelete"/>
</jcr:root>

Related

How can I subscribe to an Open event of a Word Backstage using a Ribbon (Visual Designer) object?

I want to add a button to the Word Backstage. That button is supposed to be enabled/disabled only when one or more Word documents are open in Word.
Is there some event I can use to set the state of my Backstage controls the moment the Backstage is displayed?
NB: As a workaround, I could subscribe to the DocumentOpen event, but not to a DocumentClose event, as it doesn't exist. So that solution isn't safe to use.
The backstage UI provide the onShow callback which you may find helpful.
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="Ribbon_Load">
<backstage onShow="Backstage_OnShow">
<tab idMso="TabSave">
...
Also you may find the onHide callback helpful:
<?xml version="1.0" encoding="UTF-8"?>
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">
<backstage onHide="onHide" onShow="onShow">
...
</backstage>
</customUI>
The callback should have the following signature:
public void Backstage_OnShow(object contextObject) {
}
You can use the IRibbonUI.Invalidate method to get your callbacks invoked. For example, if an add-in writer implements the getEnabled callback procedure for a button, the function is called once, the state loads, and then if the state needs to be updated, the cached state is used instead of recalling the procedure. This process remains in place until the add-in signals that the cached values are invalid by using the Invalidate method, at which time, the callback procedure is again called and the return response is cached. The add-in can then force an immediate update of the UI by calling the Refresh method.
Read more about that in the Dynamically Changing the Visibility of Groups and Controls in the Office 2010 Backstage View article.

Customizing AEM dialog - increasing all field's sizes

I have a carousel component for which there is a touch UI dialog naming '''cq:dialog''' .I need to increase size of all the fields of AEM dialog. Can anybody help me with this?
You can extend the aem style sheets by creating a clientLib:
Create a folder on file system. In this folder put a file with name content.xml.
The content of this must be
<?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:ClientLibraryFolder"
categories="[coralui3]" />
The most important thing is categories=[...]. The name of categoriy must be "coralui3".
During deployment your own css styles will be virtuelly added to your enviroment.
Then put two files into the folder. One file must be named with css.txt. The name for your other one can be named by your own. In example 'myown.css'. Open css.txtand put the name of your css file into it. See also this video on youtube.
If you want to apply your style on all dialog widgets, you style classes must be named like the classes from AEM itself.
In case you want to apply partially, you have create your own css class. Then open your dialogs xmls and add the keyword "granitCss=" to you prefered widget. See also here.

How to use children editor on a list component's dialog on AEM?

I am trying to enable children editor on a list component's dialog to allow users to add custom component into it, like the carousel component from core.
I use AEM 6.5, and the sling:resourceSuperType is list from core.
My .context.xml of the component is as follow:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
cq:isContainer="{Boolean}true"
jcr:primaryType="cq:Component"
jcr:title="List"
sling:resourceSuperType="core/wcm/components/list/v2/list"
componentGroup="MyContent"
teaserDelegate="thisPackage/components/content/teaser/v1/teaser" />
The HTML file of the list component, which is named "list.html" is as follow:
<sly data-sly-use.list="com.thisPackage.aem.dna.core.models.v1.List"
data-sly-use.template="core/wcm/components/commons/v1/templates.html">
<sly data-sly-resource="${resource.path # resourceType='wcm/foundation/components/parsys/newpar', appendPath='/*', decorationTagName='div', cssClassName='new section aem-Grid-newComponent'}"
data-sly-test="${wcmmode.edit || wcmmode.preview}">
</sly>
</sly>
I could open the component's dialog on edit mode. however, if I add new components to the new children editor on dialog and try to close the dialog. I can't close the dialog.
The error message is:
org.apache.sling.api.resource.PersistenceException: Unable to commit changes to session
I followed the example in "github.com/adobe/aem-core-wcm-components/issues/696", and move editConfig from carousel to my list component. But, it didn't solve the issue.
What can I do?
This is not working because the servlet which is responsible for updating data is of resourceType = core/wcm/components/carousel/v1/carousel
You can see in the network call that XHR request is sent to the server which has url like :
http://localhost:4202/content/we-retail/language-masters/en/jcr:content/root/responsivegrid/carousel.container.html
As you can see a selector container is sent and underlaying servlet :
https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/internal/servlets/ContainerServlet.java
is listening to only core component resource-type.
In your case it is custom component, hence resource type does not match and hence you get the error.
Two things are possible:
1: Quick and easy is to just use sling:resourceSuperType = core/wcm/components/carousel/v1/carousel
Create custom clientlibs same as this:
/apps/core/wcm/components/commons/editor/dialog/childreneditor/v1/childreneditor/clientlibs
but change var POST_SUFFIX = ".container.html"; to your own selector
and then create your own servlet (registered to your own defined selector) same as the core component.
Hope it helps!
This is a bug on AEM 6.5, and the team is working on it.
https://github.com/adobe/aem-core-wcm-components/issues/985

CQ5 preload a parsys with components

I'm curious if anyone knows how to have a parsys load w/ default components already in it.
What I'd like to accomplish is the following:
Form Component
- form-parsys
- input component
- input component
For the most part this was pretty straight forward. I created a "form" component that has a parsys in it. What I would like is for this form component to load with a few default input components already set. These input components would need to be a part of the form-parsys node, so that they can be reorganized amongst user added input components.
Not sure if there is any documentation out on this as I couldn't find any, but I'm sure it's not entirely impossible and wanted to see if anyone has done anything like this before, before I go ahead and start hacking away.
thank you
Brodie
I think what you are looking for are templates.
In CQ5, templates can be used to create pages with a predefined content, this can be a parsys (with components) or any other node you might want in your page when it is created.
In your case, you can define a template that includes a parsys component and whatever you want inside that parsys. You can also set rules for where a page can be created using that template.
After you have created (or edited, since you might already have one) the template, you can use the siteadmin to create a new page using your template. The page will be created and all the content below the jcr:content of the template will be copied into the new page. You can even have several templates for the same kind of page, if you need different types of 'initial contents'
An example of a template that includes a parsys with some content might look like this (I'm writing this mostly from memory, might have errors):
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:description="A form"
jcr:primaryType="cq:Template"
jcr:title="A form"
allowedChildren="/apps/app1/templates/home_page"
allowedParents="/apps/app1/templates/form_page"
allowedPaths="[/content(/.*)*]"
ranking="{Long}100">
<jcr:content
jcr:primaryType="cq:PageContent"
sling:resourceType="app1/pages/form_page">
<parsys
jcr:primaryType="nt:unstructured"
sling:resourceType="foundation/components/parsys" >
<component
jcr:primaryType="nt:unstructured"
sling:resourceType="foundation/components/text"
text="here is some text"/>
<!-- more components here-->
</parsys>
</jcr:content>
</jcr:root>

CQ5 widget with xtype hidden

I am trying to add a hidden property (key-value pair) to a page using a 'hidden' xtype in the page properties. But the property always returns a null/blank
The widget code is as below.
<vanitycheck
jcr:primaryType="cq:Widget"
defaultValue="myValue"
hidden="{Boolean}true"
name="./myKey"
value="myValue"
xtype="hidden"/>
The JSP code is as below:
<%=currentPage.getProperties().get("myKey" , "") %>
Are you opening the dialog? The default values held in the dialog.xml will only get applied after editing the component & saving it (i.e. the dialog has to be brought into play — they're defaults for the dialog itself, not the JCR).
If you want a default value held in the JCR when the component is created, put a cq:template.xml file in your component alongside your dialog.xml. This will specify default properties that get added into the node on creation.
E.g., you could have a file:
<?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"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
defaultValue="myValue"/>
EDIT:
For default values within templates, edit the .content.xml file under /apps/[your-design]/[template-name]/.content.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Template"
jcr:title="Content Page Template">
<jcr:content
jcr:primaryType="cq:PageContent"
sling:resourceType="foo/components/page/bar"
defaultValue="myValue"/>
</jcr:root>
Either of these solutions though will only work on newly created content (i.e. a new component for cq:template.xml or new page with .content.xml).
For existing pages, default values in the dialog can be used, as you suggested; but since these values only get loaded when the dialog is opened & saved to the JCR on "OK" within the dialog, it requires the user to edit the Page Properties on each page in order to persist the values to the JCR.
If this isn't suitable, using a fallback value in the JSP/class might be the preferred solution: resource.get(defaultValue, "myValue");