If the previous content provides quite a bit of detail about initializing the project, we still catch up with the error "Blank Page" when open en.html or us.html. As a result, where does that error happens? Perform statement queries "SELECT * FROM [nt:base] AS s WHERE ISDESCENDANTNODE([/content/eduzone]) AND [jcr:primaryType] = "cq:Page"" also give two existed pages.
Now, try to open file en.html in folder ui.content. You will see code generated by AEM from manipulation drag/drop with the content-page template. Go to path "ui.content\src\main\content\jcr_root\content\eduzone\us\en.html". You will see the structure of the template.
<?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:Page">
<jcr:content
cq:redirectTarget="/content/eduzone/us/en"
cq:template="/conf/eduzone/settings/wcm/templates/page-content"
jcr:primaryType="cq:PageContent"
jcr:title="us"
sling:resourceType="foundation/components/redirect"/>
<en/>
</jcr:root>
All I will do now is explain the basic structure of the template above. Actually, it's quite a bit complex to understand a whole or, generally, architecture built from AEM.
Besides more examples, Suppose we define jcr:EditConfig and then having collections of Child Node Definitions as cq:actionConfigs, cq:dropTargets, cq:formParameters, cq:inplaceEditing, and cq:listeners.
And jumping into folder ui.content generates automatically code like below.
<?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:EditConfig">
<cq:listeners
jcr:primaryType="cq:EditListenersConfig"
afterchilddelete="CQ.CoreComponents.panelcontainer.v1.AFTER_CHILD_DELETE"
afterchildinsert="CQ.CoreComponents.panelcontainer.v1.AFTER_CHILD_INSERT"
afterchildmove="CQ.CoreComponents.panelcontainer.v1.AFTER_CHILD_MOVE"/>
</jcr:root>
editor.html creates a considerable significance about UI when sidebar right will provide details of Assets, Content Tree and Components. This help user can examine or adjust any things from the website. Could you remove it? That means we are publishing the website on the client-side.
So that why creating a page by select Content Page gives the same result (blank page). In part two, we will mention components, elements, or configurations that need to institute a page before rendering in the local instance of AEM.
Actually, there are many things inside CRXDE | Lite, and then get us not pay much attention to the project's structure. It is really has a bit of confusion between folder as ui.frontend, ui.apps, and ui.content. Now, let concentrate on the ui.apps and expand each folder to reach folder eduzone have subfolder as clientlibs, components, and i18n. We will start building some essential components and structure pages for the website.
The content mainly focuses on the components folder and builds individual folders as content, form, and structure (page inside the structure). Actually, the architecture has a similarity to the AemSorl2 project in the article.
Note: Be possible to remove all default components inside folder components, and we can create some basic components if necessary for the eduzone project. Please attempt to ensure all steps exactly and don't miss any steps to following the article.
If we spent much time devote attention to the structure of CRXDE | Lite and then we can be aware that many great options allow creating node, file, folder, template, component, and dialog. Try to run command "mvn -PautoInstallPackage -Padobe-public clean install" to deploy module app, all, and content to an instance of AEM.
Jump into the path "/apps/eduzone/components/structure/page," and we have a structure like below:
Following the step below, create the page's structure with a header, footer, and also other parts of the website as sidebar, body,...
From these fundamental analyses, we can define file customfooterlibs.html as below. Can call variable clientlib as a variable that exposes from clientlib.html (Client-Side Libraries). As a result, use syntax @{clientlib .js } allows drag tag <script> from front-end page into its template (customfooterlibs.html).
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientlib.js @ categories='eduzone.base'}"/>
</sly>
Suppose we argue a similar way with file customheaderlibs.html. It is straightforward to know CSS can be passed inside the standard web page HTML tag header.
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
<sly data-sly-call="${clientlib.css @ categories='eduzone.base'}"/>
</sly>
As a result, you no need to create yourself customizations that ARE provided. For instance, page.html has completely structured with each particular part as head.html, footer.html, redirect.html, etc... Your target custom the page.html which is suitable with the project.
<!DOCTYPE HTML>
<html data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page" lang="${page.language}"
data-sly-use.head="head.html"
data-sly-use.footer="footer.html"
data-sly-use.redirect="redirect.html">
<head data-sly-call="${head.head @ page = page}"></head>
<body class="${page.cssClassNames}">
<sly data-sly-test.isRedirectPage="${page.redirectTarget && (wcmmode.edit || wcmmode.preview)}"
data-sly-call="${redirect.redirect @ redirectTarget = page.redirectTarget}"></sly>
<sly data-sly-test="${!isRedirectPage}">
<sly data-sly-include="body.socialmedia_begin.html"></sly>
<sly data-sly-include="body.html"></sly>
<sly data-sly-call="${footer.footer @ page = page}"></sly>
<sly data-sly-include="body.socialmedia_end.html"></sly>
</sly>
</body>
</html>
We had a declaration as ${page.language} in paragraph tag <html>. The variable page is known as the global variable in HTL language. Reference link here and analyze the relationship between Java, HTL, and JSP for a little bit. Move back to the small exercise named "How to pass data from client to JSP?." Suppose that from client/server return data and express data under the parameter demo (localhost:3000/demo=Hello+world). We will print the value "Hello world" in file JSP.
<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
<% String val = request.getParameter("demo"); %>
</body>
</html>
If we pay attention thoroughly to the syntax above, the request can be seen as a global variable in Java similar to the object page. The method getParameter() is the return parameter, but Java using getter/setter for access data inside an internal class. Will we have a method similar to getParameter() with attribute language won't us? The exact answer has "YES." You should access the path "https://github.com/adobe/aem-core-wcm-components/blob/master/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/models/Page.java" to see all method get/set inside the class.
/**
* Returns the language of this page, if one has been defined. Otherwise the default {@link java.util.Locale} will be used.
*
* @return the language code (IETF BCP 47) for this page
* @since com.adobe.cq.wcm.core.components.models 11.0.0; marked <code>default</code> in 12.1.0
*/
default String getLanguage() {
return null;
}
As a result, the syntax should rewrite properly below. Actually, it is right for the JSP template. But with the structure of using HTL and we have quite a bit different in the declaration.
<html data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page" lang="${page.getLanguage()}"
About HTL1
<html data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page" lang="${page.getLanguage}"
About HTL2
<html data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page" lang="${page.language}"
With the JSP template, we might process some basic manipulations as convert to lower case or upper case,... That is also applied similarly in HTL template.
<html data-sly-use.page="com.adobe.cq.wcm.core.components.models.Page" lang="${page.language.toUpperCase}"
/**
* Returns the title of this page.
*
* @return the page's title
* @since com.adobe.cq.wcm.core.components.models 11.0.0; marked <code>default</code> in 12.1.0
*/
default String getTitle() {
return null;
}
From these analyses above, we summarize an initialization code.
<template data-sly-template.head="${ @ page }"
data-sly-use.headlibRenderer="headlibs.html"
data-sly-use.headResources="head.resources.html">
<meta charset="UTF-8">
<title>${page.title}</title>
...
Beside, we also have other methods as getKeywords(), getTemplateName(). It leads templates to add some more tags.
...
<meta data-sly-test.keywords="${page.keywords}" name="keywords" content="${keywords}"/>
<meta data-sly-test.description="${properties['jcr:description']}" name="description" content="${description}"/>
<meta data-sly-test.templateName="${page.templateName}" name="template" content="${templateName}"/>
...
But, look over template head.html; we won't have the tag "viewport" that support responsive website in all platforms.
...
<meta name="viewport" content="width=device-width, initial-scale=1.0">
...
Hello world