AEM - Apply separate styles to authoring view and publishing view for component - content-management-system

I'm using Adobe Experience Manager and i need to apply separate styles to authoring view and publishing view for component. The reason for this is I have some JS that changes the layout of the component at desktop size, however in authoring mode this means the component is no longer usable or fully visible.
So far I have:
looked in Adobe Forums for a similar question
tried to add some styles within html file based on the condition of edit mode being true:
<sly data-sly-test.author="${wcmmode.edit}"><style><!--my code--></style></sly>

Instead of writing inline styles based on the edit mode, better way would be to define a separate client library and add that client library on your pages only in edit mode. Let's say, you have a component - "Custom Component" which has the class as - "custom-comp".
<div class="custom-component">
<!-- your custom component html code goes here -->
</div>
So I am assuming you would already have defined some CSS for this component in the project client library that should be loaded on your pages already. To style it different in author mode, you can try following steps -
In your page.html, define a special class which will identify whether your page is being loaded in Author or in Publish. Something like below -
< body class="${wcmmode.edit || wcmmode.design ? 'authoring-mode' : ''}">
Using above line of code, your pages will now have a special class - "authoring-mode" only when you open the page in Author. But when you open page in publish, this class won't appear which is exactly what you want here.
Now, you need to define a new client library in your code which will have CSS and JS files and you need to load this new client library in your customheaderlibs. Again this client library needs to be added only in author mode.
Write custom CSS rules for your custom component using the combination of two class names - "authoring-mode" and component class name - "custom-component".
Test your changes in author mode and publish mode.

Related

Loading a Vue file's content into a JavaScript variable for routing

I've been trying to use the vue-router package for days without figuring out how it works, and it kind of drives me crazy.
My problem: I want to make a Single Page Application using VueJS, and I have taken the vue-router package since it is the routing package officially supported by the VueJS development team.
I've read a lot of "getting started" articles, lots of them start by hard-writing the template like this:
const Foo = { template: '<div>foo</div>' }
But since I'm not really into writing my entire template between those two quotes marks, I searched for a way to write my template into a file, and then load the file's content into a JS variable.
It seems that it's possible to write the templates into .vue files, and then load them into variables using:
import App from './App.vue';
But when I do this that way I get this error: "Unexpected token import".
I'm really frustrated by that, haven't they thought about a really convenient way for the template loading to be compatible on every browser? What did I miss?
I suggest you look into Vue CLI for helping you set up a desired scaffold for your project. Based on the options you choose you can end up with a webpack backed template along with the vue-router included. Webpack will take care of bundling your project so you don't encounter errors like that one.
Generally what you want to do is use vue files. A vue file is divided into three parts, and would look something like this:
<template>
// Your HTML for this component goes here
</template>
<script>
// Your JS for this component goes here
</script>
<style>
// Your CSS for this component goes here
</style>
Once you have your components organized like this, handling routing is pretty straightforward. You designate a file to contain the router object that handles the routing.
These are pretty much basics, so I won't go into details here but you can learn a lot more on the official Vue docs page. Here is also an example project that shows how to construct simple components in vue files and how to properly use the vue-router.

cq:includeClientLib in AEM if included inside a component jsp and the component is present twice on the page

If we give cq:includeClientLib inside my component jsp and if we drag and drop the component twice on that page, will the clientlib gets loaded/included twice?
what will be the case if we do in Sightly way (data-sly-call="${clientlib.all # categories='somecategory'}") ?
And also what is the suggested method of including client libs, either create a clientlib specific to the component and load only for that component or include all the CSS and JS at a common clientlib and use it across?
No, the clientlib is only included once for a category.
This is by design as the HTL (and respective JSP tag) are evaluated during runtime and the processor keeps a map of categories that have already been included and does not include them again.
As #i.net mentioned, each category will only be included once. To answer your follow up question about the suggested method..
The best practice seems to be to define a client library for each component, which is then embedded into a "global" client library. That global client library will then be included within your page template.
/etc/designs/acme/clientlibs-all
categories=["acme-all"]
embed=[compA,compB]
/apps/acme/components/compA/clientlibs
categories=["compA"]
/apps/acme/components/compB/clientlibs
categories=["compB"]
The reason the global client library is located under /etc/designs is to prevent exposing /apps to the public. However, in AEM 6.3, you could make use of the allowProxy property to serve the code at /etc.designs/. This would then look like this:
/apps/acme/clientlibs/clientlibs-all
categories=["acme-all"]
embed=[compA,compB]
allowProxy=true
/apps/acme/components/compA/clientlibs
categories=["compA"]
/apps/acme/components/compB/clientlibs
categories=["compB"]
Adobe recently released a good tutorial of more recent best practices around client library structure: https://helpx.adobe.com/experience-manager/kt/sites/using/getting-started-wknd-tutorial-develop/part3.html

how properties are stored in /etc/designs for design dialog

I'm new to CQ5 and working on a project that deals with refactoring code that uses design dialogs.
Currently, I have a property declared as part of design dialog of my component. It creates a folder in /etc/designs/ for each template my component is used on. Is there a way we can make sure that those property values are stored at one particular configuration in /etc/design(as opposed to multiple)? I need to make sure only one set of configurations is used for all pages that use my component.
Thanks in advance!
Pallavi
The designs are linked to the template and not the whole site.
Hence whenever you configure the component in design mode, the values are stored within the corresponding template under the jcr:content of the configured design page or under /etc/designs/default/jcr:content in case no design is configured.
As far as I know, there is no way to tell AEM to store all the design configurations under one single path, unless you are using absolute paths in your dialog / page configurations.
If you are using multiple templates in your site, there must be one master template (which render global components eg. header/logo/navigation & footer), and all other templates should extend master template to get these global components and change pagelayout for content section.
Saying so, if templates are structured & inherited properly, you should be able to set design dialog property on home page (created using master template) and all internal pages will be able to access those design property OOB. Though child pages (created using other template) can override those design property (if needed for that template) to break inheritance.

How to change the website look and feel by changing the design location under page properties

I have a requirement where I have 2 clientlibs having different CSS files for my website. The business author should be capable of switching the website look and feel by just changing the path of the design under page properties. While I am able to achieve that requirement by changing the clientlib categories name referred in my JSP of base template of my site, can the same thing be achieved by the business author without actually performing a code level change? Basically, he should be able to select the design path present under the page properties section, and selecting a different design should change the look and feel of the website. Please let me know how this can be achieved.
Note: I have placed my clientlibs under /etc/design/proj-name/ path
The foundation page component is designed to include css link in the head if a file called static.css is present under the design. It's done through the design object.
If you have different css in the static.css file under different designs then the look and feel will change with the design. However you will be stuck with one file and cannot leverage the utility of client libs.
This adobe doc suggest's doing something like this for css and related images
<%= currentDesign.getPath() + "/static/img/icon.gif %>
Data from design dialogs is stored under the design , swapping designs to change look and feel will cause data inconsistencies too.
Why not add a selection widget to the page and use it's value to selectively include different client lib categories instead of relying on the design.

How are themes applied in Adobe AEM?

The Client Library (ClientLib) feature in Adobe AEM (formerly Adobe CQ) makes it easy to include client libraries by category and each library can pull in other libraries through dependencies. However the documentation around "Themes" is a little thin.
This link is about all I can find on the subject. Here is an excerpt of the sample code:
<%-- theme only (theme-js + css) --%>
<cq:includeClientLib theme="cq.collab.calendar, cq.security" />
If this tag were to be used how would CQ determine what Client Libs to pull in? Does it look for a theme property of type String[]?
Or does it look for a certain directory structure in the /etc/designs section?
Or does it take the passed in categories and add theme-js to the end like so?
cq.collab.calendar.theme-js
Or is the theme invoked through the URL? In other words, the word "theme", in this case, is a token that is replaced with a selector from a URL applied theme?
Client Libraries reside in a cq:ClientLibraryFolder folder. This folder has a property called category. In the following example, cq.collab.calendar and cq.security are categories:
<cq:includeClientLib theme="cq.collab.calendar, cq.security" />
When this include is called, it is looking for any cq:ClientLibraryFolder with the category cq.collab.calendar or cq.security assigned to it. Using the theme property adds both the css and javascript of clientLibs residing in the themes folder of the parent ClientLibraryFolder. If you were to view your page source, these would be added to their own css and js files. For example, I created the following structure under the geometrixx clientLibary:
geometrixx
clientlibs
themes
myTheme (clientLibray)
css.txt
myCSS.css
js.txt
myJS.js
If, you use the theme property with this clientlib you would get a myTheme.css and myTheme.js file showing in your source/network tab.
The themed flag is a way to shut theme inclusion on and off. The following cq:include will include all the css in the clientLibrary, including stuff in the themes directory.
<cq:includeClientLib css="apps.geometrixx-main" />
However, if I add the themed flag and set it to false, anything under the theme directory is excluded:
<cq:includeClientLib css="apps.geometrixx-main" themed="false" />
So in that case, myTheme.css would not show up. One thing to note, is that the themed flag, only works on "pure css and js includes" Categories and theme properties would not work with this.
The answer to this question goes over this a bit: What exactly does currentDesign.writeCssincludes include?
It has been mentioned that theme is fetched from the request did a little digging an finally found out it tries to fetch it from request parameter named "forceTheme"
private String getDefaultThemeName(SlingHttpServletRequest request)
{
String theme = request.getParameter("forceTheme");
if (theme == null) {
theme = this.defaultUserThemeName;
}
return theme;
}
But needed request.getAttribute because using query parameters will send all requests to pub.
So guess this theme option is of no use at all.
Depends on what you mean by "theme". If you are used to wordpress, drupal, etc, what is called a theme in those systems is called a "design" in CQ5/AEM.
To set a design, you choose a "designpath" in the page properties. This will affect where information about components for each template is stored (all changes made in design mode about what components are allowed where are stored under this path) and is the convention for where CSS, JS, and non-DAM image resources are stored. It takes planning, but you can re-use code and markup in AEM/CQ5 but totally change the look by changing the design.