trigger a save programmatically in a custom AEM component - aem

We have the need to create a custom AEM component that is able to trigger a save to the JCR programmatically (in the location of the page that is being edited). When building a custom AEM Component, you don't need to call the 'save' logic manually, you just add a <content> tag, and AEM will automatically add the content to the JCR when saving the dialog.
How can manually trigger the same save operation that would be executed when clicking the 'save' button on the custom AEM Component?

The AEM page/template editor does async POST requests when you drag'n'drop components on a page, for example:
You can implement an async request as well for your save button and leverage the Sling POST Servlet or your own custom servlet to add to the JCR.

Related

How to access input field in TinyMCE 5 URL dialog

I'm porting a TinyMCE 3 installation to version 5. I set up a toolbar button that opens a dialog that contains a custom page and is therefore loaded using the new windowManager.openUrl method. I have some footer buttons, too, and, of course, an onAction( dialogApi, details ) handler that is invoked when a button is clicked. details.name contains the name of the button that was clicked so I can react on every click individually.
It seems, when a regular dialog is used, I configure every input field in my plugin.js file and retrieve its value through the getData method of first param that in passed into my onAction handler. This method does not exist in my dialogApi for the URL dialog.
My iframe/dialog contains a dropdown and I want to insert the selected value into the editor instance when a dialog footer button is clicked. I understand I can use postMessage to send information from the iframe to the plugin but that's not what I want.
How can I access input fields in the dialog, when a button is clicked and my dialog was opened through openUrl? How do I access the document in the dialog's iframe? this seems to be the JavaScript object I passed into openUrl. document is the page where the editor is embedded.
I've made a demo that shows two different ways of getting the data from user inputs in an iframe dialog:
https://codesandbox.io/embed/tinymce-dialog-openurl-demo-fpfew
This blog post is also an excellent resource for working with iframe dialogs in TinyMCE:
https://www.martyfriedel.com/blog/tinymce-5-url-dialog-component-and-window-messaging
The first method in my demo uses a button in the HTML of the iframe itself. That button collects user data and uses postMessage to send that data back to the TinyMCE editor.
As you can see, the process is a little more complex using the footer buttons as opposed to the "in iframe" button. Essentially, the footer button sends a message to the iframe in the dialog asking the iframe to collect and insert user data into TinyMCE.
When using an iframe, you have to respect the browser security policy, so most times you can't interact with an iframe directly (the exception being if the iframe uses the same domain). Here's some more information about iframe security policy:
https://security.stackexchange.com/questions/67889/why-do-browsers-enforce-the-same-origin-security-policy-on-iframes
This also means that TinyMCE has no way of knowing what's inside the iframe like it does with a TinyMCE dialog, so the data needs to be fetched "manually". With that in mind, if it's a cross origin request (different domain) there's no way to access the iframe content without using postMessage.
The getData method mentioned works with TinyMCE dialogs because everything in the dialog is a TinyMCE component. TinyMCE components have a custom concept of values/states that getData can access to return data.
When you use a URL dialog, the dialog no longer uses TinyMCE components so it isn't able to collect the data for getData, hence it the method doesn't exist. That's why you have to manually get the data needed from whatever elements are in the URL dialog, and send them back to TinyMCE using postMessage.

How can I call a cstudio action from a webpage in Crafter

I've created a webpage in Crafter CMS (version 2.5.2) whose purpose is to help edit a Crafter Component. I'm doing this in my page instead of in the CStudio Panel because I want to search/filter for specific components (I have 1000s). I'm editing the components using Crafter's In Context Editing capabilities, but I want to be able to call actions such as Create New, Delete, Approve & Publish, History, etc on a selected component. Is there any way I can do that from my web page along with the UI (e.g. Create New pops up normal Create New modal dialog, History pops up history dialog, etc.).
Crafter CMS uses a message pump between the preview pane and the studio application to inform the application of actions taken "in-context." within the preview pane. Messages (operations with metadata) are pumped by the system automatically between the two contexts (the studio application and the preview pane.)
"Edit" is currently a valid message/op.
"Delete" is currently a valid message/op.
However in 2.5.2 there is no "New" message/op.
In order to fire a New Op message you would need to register the message and build the handler (all Javascript) that fires the appropriate javascript APIs for the app. To fire a New operation you only NEED a path to where the content will be created in the message as metadata. The App already has code to look up permissions and check if which content types are available at that path.
Javascript files of interest:
Fire the message
/static-assets/components/scripts/guest.js
Handle the message
/static-assets/components/scripts/host.js
Declare the valid messages
/static-assets/components/scripts/crafter.js

common component across all CQ5 pages

I have created menu component, through which authors enter name, url field values.The component script renders the menu based on name, url entries.
Question : how to make this menu component common across all CQ5 pages, so it is not drag and dropped on each page.
Thank you,
Sri
ACS AEM Commons now supports this functionality without use of an iparsys - Shared Component Properties (http://adobe-consulting-services.github.io/acs-aem-commons/features/shared-component-properties.html)
Configure your menu with Shared and/or Global properties and you can simply template it directly onto all of your pages (no iparsys required). You can then edit the menu from any page on the site and it will by updated on all pages.

Forcing page reload from Vaadin portlet

Is there an easy way to force the entire page to reload from Vaadin? I have a portlet which affects the header value displayed which is pulled from IBM WebSphere's dynamic cache in a separate JSP.
I am porting over an old JSF portlet to Vaadin which depending on page reloads between actions to reflect the new value in the header template. So now I need to force the entire page (not just the portlet) to reload to make it appear that the action took effect.
You can reload the hosting web page with JavaScript:
getMainWindow().executeJavaScript("window.location.reload();");
I think this should also do the trick in a portal.

How to use normal ajax request on any jsp/servlet to get response

I want to create login form in CQ5 using normal JSP & AJAX request with database. Can any one tell me the steps how to use normal JSP and AJAX in CQ5?
At the server-side, an AJAX handler can be implemented the same way as an HTML handler, in CQ5. Create your CQ template with a standard backing component. In your component, code your JSP as your normally would, following CQ best practices such as including "/libs/foundation/global.jsp" (or your overridden version of this). You'll have access to all normal JSP objects such as request and response. global.jsp also includes JSTL, so you've got access to standard taglibs.
As for connecting to a database, see my other answer, External Database with Adobe CQ5.