Global Configs - reggie7/aem-tools GitHub Wiki
A lot of features within AEM Tools are my response to what I consider bad (and often ugly) practices. Zoom mode is an answer to unnecessary referencing and/or flooding author's page view. Global configs here is my PoC for how one can easily overcome a couple of other issues with one simple solution.
AEM incorporates some fine tools that can be very helpful when used properly. But unfortunately they can sometimes be easily miunderstood, misinterpreted and used where they should not be. These might seem convenient, simple solutions of a problem, but I believe that not always an initially easiest path is the best in the long run. And some shortcuts taken now will be painful later as e.g. the data design might get flawed. Two such examples that I've seen (and I cried as I had to conform my development) in production are how cloud service configurations and i18n.
So basically I believe in content. I think that anything the end user (the published content viewer) can see and read shall come from content branch. Or at least as much as possible should. But actually I've seen implementations where the content of published pages was spread throughout all content, i18n and cloud services (fortunately I don't remember labels configures via console - this would just be too much...). Simple button labels like OK, Cancel, Apply were configured in i18n. Some labels like e.g. Search or Menu got placed inside cloud services. Obviously most of the content got where it's supposed to be. But otherwise - no sensible order whatsoever was imposed. Just as if some developers were like I'm gonna put this here and that there, why not? and others - the other way around. With no logic behind it, simply because it would be faster than figuring out a better way to do it. On the other hand - with a confidence of thinking out of the box. But the box seems so far away here...
Why is it bad? Well - it just doesn't feel right somehow first of all. Other than that Cloud Services are maintained by one group of users. I18N is maintained by a different group of users. Authors that create content usually do not have access to those other parts of the app/content management. It makes little sense to restrict configuration for such labels like Search or OK... Content-centered approach seems compact, consistent, uniform and more natural. Or am I wrong and I can't see something here?
CCs and i18n might sometimes seem like a time-saving solution, but in general it is not, their purpose is different. Inherited properties for shared content can be used instead for instance. Labels, images, texts usually belong to underneath /content, not /apps (where i18n is stored) or /etc (where CCs are located). The following would be a cheat-sheet to follow:
- Use i18n for whatever an author will see, but the end user will not. I18N is the AEM application, not the customer website.
- Use CCs for whatever neither the author nor the end user will see directly. This is configuration (not content) for services that are external to the AEM instance. They are not content holders.
A label for Search does not belong to CCs. You can e.g. create a search component and force a resource named search inside jcr:content of the language/home page. If needed elsewhere - inside other pages you will simply render the same resource by providing an absolute path (pointing to the search of home page). An example could be how header is configurable in lang page but only referenced elsewhere.
Generally - I'd rather keep content as close as possible to the resource that needs it. Unless there are reasons to split it. One could be reusability of course. But why complicate things otherwise?
Anyways - I'm not saying I've got the perfect solution. But I am saying I have a solution. Or a set of rules for a solution.
My PoC for global configs lies within every page at the bottom - let's check en then. We'll find an instance of configs there and we can zoom in to see the full view of what one can configure there. Currently mobirise configs extends base enigmatic config that takes advantage of its super - complex. So basically complex.html gets rendered in the normal view. And then zoom view is using the zoomed.html script.
One can put all the global configs there easily - anything you want basically. They're going to stay hidden from the regular page view and they'll reside inside the page's content. No need for referencing it from anywhere else, no need for special config pages in other content branch. Additionally in my examples the configs are available everywhere in the pages tree, so these configs can be fetched from inheritedPageProperties and then both - shared from an ancestor page and overwriten in a descendant page. It does not ovbiously have to be exactly this way, but it's possible.
A single example within aem-tools is the blog's header component. It's using a GlobalConfig model to fetch a date format to use from the global configs.
Another example covers the issue of reusing labels. The configuration component again takes advantage of base config component. The configuration is again placed at the bottom of the page. Upon entering zoom a configuration page shows up. Values for the labels can be set in there. They could easily be used via
${inheritedPageProperties['labels/<label id>']}
but to add some more functionality I've introduced GlobalLabels model.
Blog's header component uses this approach to fetch two globally configured labels. Additionally the labels are presented within a select inside dialog of a link. A provider class GlobalLabelsOptions exposes all the labels for the datasource.
All of the above (besides my complaining on the ugliness I've seen out there) is just a proof of concept. The actual UX design for a production environment would be easily customizable. The configs don't need to be placed on every page, the labels don't need to be so complex and (possibly) overengineered. On the other hand - I believe one would eventually become familiar with the concept and it would be natural and easy to use both to a developer and for an author.