Pass variable from component model to author dialog - aem

I have a Sightly component with a (JavaScript) UseAPI model in an Adobe AEM/CQ site.
In the model, I have a variable that is calculated when the component loads and is not stored in the JCR (let's say it's a random string).
When an author opens the Granite/Touch UI dialog, there is a custom Granite UI component rendered with a JSP. The JSP has access to the scope of the component in the JCR, but as far as I can tell it does not have access to properties returned by the JavaScript model when rendering the component.
How can I pass/store this 'random string' variable from the Sightly/JavaScript UseAPI so that it can be accessed by the JSP of the dialog?
The variable is context-sensitive so I wouldn't want to store it in a permanent location such as the JCR. A good example may be a unique identifier for an external web service, that is unique for that particular rendering of the component.

I can think of a couple of approaches, with varying applicability:
Dialog field emptyText property: This just shows grayed out/hinting text and does NOT set any content that can possibly be rendered.
Dialog field defaultValue property: This looks very tempting, but I don't recall having success with it.
Dialog event handlers: (adding JavaScript inside the XML of a dialog definition). I am not a fan of this approach since it isn't obvious how/where the magic happens. But it is possible to update/populate fields on dialog load or dialog save.
Component cq:template: just like a page template, you can provide default content when dragging a component into a parsys. This doesn't work for components cq:included into the page/component. Also, it doesn't prevent the author from deleting the value altogether unless you add event handlers on the dialog.
Create a component model. The model can provide default content/values if properties are missing or not populated. The drawback is authors may not understand where magic values are coming from if dialog fields are blank. Once I worked around this by creating a tag that would use authored values, then fall back to dialog emptyText properties, then to possible template values to "fill in" the content. This takes some initial developer effort, but provided hints to the authors if the content was missing, or the component was included instead of dragged on, ...YMMV.
However, none of these may work for you if the value is "context sensitive" and has to be calculated somewhere/somehow. But if it is computed, then it probably shouldn't be authored.

Related

TYPO3: Difference between Plugin and Custom Content Element?

I have to implement a media download feature. The backend user should be able to upload a media file, set the title, description, release date and so on... The result should then be visible and the file available for download in the frontend.
I am not sure what is the best way to achieve this: Plugin or Custom content element ?
Whats the main difference between the two and what would be the best solution for my task ?
Plugins are used for more complex rendering of records with different views (for example a list and a detail view of records stored somewhere in a storage folder). A custom content element (CE) should be preferred if all relevant data is stored in the record.
For your case, a Content Element seems to be the right solution. This kind of custom content elements can also be easily created with helpful extensions like "mask" which may takes you 10 minutes to create a custom CE.
https://typo3.org/extensions/repository/view/mask
If I understood you properly.
You can define plugin as type of "list_type", or as "CType" (if you need to code specific function, which is hard or unable to achieve using eg. Fluid contents) or even as another menu type defined as "menu_type".
These all types can be the same way made plugin, this separation for types are basically only for making it appear in different selectors. So:
your plugin defined as menu_type is to be selected in "Special Menus" content type in "Menu type" selector,
defined as list_type (so called) is to be selected in "Insert Plugin" content in "Selected plugin" selector,
defined as CType is totally new content type.
But they work the same way and this is easily to be switched using parameter in ext_tables plugin register call:
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPlugin( ['Label', $_EXTKEY.'_myPluginSuffix'], 'CType');
1) You can use the "File Link" content element and adapt its TypoScript (tt_content.uploads.20.renderObj) to your needs.
2) You can use the file_list extension and adapt its Fluid templates to your needs

symfony custom form type with assets

I've created a custom form type in symfony2. This formtype has it's own template and this is working fine.
The form type also needs some javascript on the clientside to work nicely.
I would like to add this javascript to the page using the same template I use to render the widget. It's a bit more of a hassle to do this manually.
I could add the javascript manually on each page, but it would be nice if that just happened automatically.
I can't add the javascript just before or after the element itself, as it has a dependency to jquery which is only loaded at the bottom of the body.
I tried using a block which is defined in the "main template" (it is named block_javascript) to add the custom javascripts to the footer of the page, but it seems the rendering of forms works a little different and the block is not available.
I'm using assetic to prepare and return assets.
Is there a way I can use blocks from the main template being rendered when rendering a form widget?
I don't think yet about all the consequences or if it's doable, but here an idea that can solve your problem: use the event dispatcher.
an event for assets addition
a service that hold a list of assets to use and subscribe to above event
a Twig extension that use above service to make assets accessible in the template
trigger the event in the buildView() function of your form type with right parameters
use the Twig extension in your layout template
It theorically should work.

How to get a component to show up in the list of draggable components (for parsys)?

I'm trying to create a component that I can drag into a parsys component, but for some reason it doesn't show up in the list of available components (see images below). I'm pretty new to AEM, so if I sound ignorant, I probably am (edits to this question are welcome).
The first and the foremost requirement for your component to be draggable is to have either a dialog or design_dialog.
Second, it shouldn't be part of the component group .hidden. It is fine if it doesn't have a componentGroup property at all, you can find it under NO GROUP DEFINED.
Set the allowedParents property of type String[] to */parsys.
And finally make sure that the jcr:title is different from the name of your component. They shouldn't be the same. For Eg: If the name of the component is text then the title should at least be Text.
I haven't worked in the touchUI, but for sidekick this holds good. So I guess it should work for your case too.
First: Make sure you have a dialog defined.
Second: Ensure that there is a componentGroup defined that doesn't start with a period. ANY group name that starts with a period will hide the component.
Third: Make sure the component is enabled with design mode.
AEM Mastery blog post about getting a component to show in the sidekick

How do we define global properties in CQ5

My Requirement is to have a global header and footer with author able properties.
So if we update the properties on one page it should be reflected across all pages.
What is the best approach to achieve this in CQ5.
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 header/footer from any page on the site and it will by updated on all pages.
Unlike using design dialogs, Shared Component Properties supports standard content activation and internationalization (values stored below the homepage) and anything else you would expect from content.
If all of your pages site under a hierarchy, you could use an Inherited Paragraph System (iparsys). This is from an old version of the documentation, but is still a good intro:
The inherited paragraph system is a paragraph system that also allows
you to inherit the created paragraphs from the parent. You add
paragraphs to iparsys at for example, /content/geometrixx/en/products
and as result, all the subpages of products that also have iparsys
with the same name inherit the created paragraphs from the parent. On
each level, you can add more paragraphs, which are then inherited by
the children pages. You can also cancel paragraph inheritance at a
level at any time.
While not quite what you're describing in the original post (edit anywhere) it will allow you to edit the content once (at the parent page) and inherit the changes everywhere.
Traditionally you could create the components and swap the dialogs out for design dialogs. Basically you would rename your component dialog to design_dialog.
What this will do is save the changes you make to this object to a design path under etc. You can set a design path for site by going to the top level parent and setting a designPath property.
So node structure might look something like
parentNode
- #prop designPath = "designs/myapplication"
childNode1
childNode2
etc...
Any component using a design_dialog on the parentNode or its children nodes will get their information from the designPath. If you do not set a design path, the infomration is saved under etc/designs/default (or defaults, not sure, going off the top of my head).
There are some alternatives to this:
What our team did was in our siteHeader component we use http://dev.day.com/docs/en/cq/current/javadoc/com/day/cq/commons/inherit/InheritanceValueMap.html (inheritancevalue map) instead of the regular value map. The inherited value map will traverse the tree up looking for items from it's parents. This is a great source for learning how to use valuemap instead of just the default properties object:
http://experiencedelivers.adobe.com/cemblog/en/experiencedelivers/2013/02/valuemap-and-his-friend.html
This does get complicated with larger sites, and you'll have to do a lot of customization to get the system working the way you want, but it's an option if you don't want to have to manually set designPaths for every new site your authors create.
Alternatively, if you do like the idea of using designPaths and design_dialogs, you can always hook into the page creation workflow and have the page component add a designPath property on creation (this is a lot easier said than done though).
hope that helps

Custom Field in CQ5 Page console

When we create a new page in CQ5 'siteadmin' , we get two fields to fill up ("Name" and "Title").
Could there be any way to add more fields here (Say, "Description") which the authors can fill up and it will be saved as a JCR property of the page in CRX ?
Any ideas/solutions will be welcome. I can't think of any.
You want to add custom page properties. From the linked knowledge base article:
(1) Copy /libs/foundation/components/page/dialog node to your template's
component that you want to add dialog properties to.
(2) Add fields to the dialog
Example:
If you had a page component /apps/<myapp>/components/pages/contentpage
that has sling:resourceSuperType=/libs/foundation/components/page then
you would copy /libs/foundation/components/page/dialog to
/apps/<myapp>/components/pages/contentpage/ to make an overlaid dialog