table of content
Table Of Content

    Fundamental of client-side libraries building AEM component Part 8

    Share

    I. Analyze about appearing Blank Page

    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.

    • jcr:primaryType="cq:Page": Follow the article here and then realize that jcr:content is a child node of cq:Page.

    Besides more examples, Suppose we define jcr:EditConfig and then having collections of Child Node Definitions as cq:actionConfigscq:dropTargetscq:formParameterscq: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>
    
    • cq:redirectTarget: Define the path when you want to show it in the browser. As a result, from the declaration above, if you add root domain and full path as "localhost:4502/content/eduzone/us/en.html." If we add editor.html and the path will show another way "localhost:4502/editor.html/content/eduzone/us/en.html." 

    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.

    • cq:template: The specialty of the property comes from "Primary Item Name." If we check node type and then realize that value equals "null." That determines no existed nested node inside it, and we can use it to connect with many properties to institute a whole configuration. The attribute usually comes along with jcr:primaryType="cq:PageContent" to render a page.
    • cq:PageContent: cq:template may consider as one property in cq:PageContent to detect which default template used to render. You can expand following the path "/conf/eduzone/settings/wcm/template-types/page/jcr:content" to get detail of default page in AEM.

    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.

    II. Build Structure of Page

    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,...

    • Create a file named "customfooterlibs.html." The file allows importing file JS, CSS, or client libraries inside the page by import clientlib.html. The property "data-sly-use" is one of the syntaxes of HTL Block Statements. Use it to initialize a helper object (defined in JavaScript or Java) and expose it through a variable, and data-sly-call can be seen as a data-sly-template that declares templates.


    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.

    • Create a file named "customheaderlibs.html."
    <sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
        <sly data-sly-call="${clientlib.css @ categories='eduzone.base'}"/>
    </sly>
    
    • Create a file named "page.html." We have the structure of implementation inside file page.html base on AEM Web Content Management Core Components. Let dive straight into the path "/apps/core/wcm/components/page/v2/page/page.html" and open up a file page.html.

    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}"
    
    • Create a file named "head.html." Similarly, we also inherit head.html from "/apps/core/wcm/components/page/v2/page/head.html". Observe file Page.java from "https://github.com/adobe/aem-core-wcm components/blob/master/bundles/core/src/main/java/com/adobe/cq/wcm/core/components/models/Page.java" has existed method getTitle() that allow us to the dynamical title for each page.
           /**
    	     * 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



    Flagtick Group
    Flagtick Group The individual is sociable and enjoys making friends, often sharing knowledge across various fields. |1 second ago
    Flagtick Group The individual is sociable and enjoys making friends, often sharing knowledge across various fields. 1 second ago
    You need to login to do this manipulation!