建立自訂元件

了解如何建立要與AEM SPA編輯器搭配使用的自訂元件。 了解如何開發製作對話方塊和Sling模型,以擴充JSON模型以填入自訂元件。

目標

  1. 了解Sling模型在操控AEM提供的JSON模型API中的角色。
  2. 了解如何建立新的AEM元件對話方塊。
  3. 了解如何建立與SPA編輯器架構相容的​custom AEM元件。

您將建置的

先前章節的重點是開發SPA元件,並將其對應至​現有的 AEM核心元件。 本章將著重說明如何建立和擴充​new AEM元件,以及如何操作AEM提供的JSON模型。

簡單的Custom Component說明了建立新AEM元件所需的步驟。

全大寫顯示的訊息

必備條件

查看設定本地開發環境所需的工具和說明。

取得程式碼

  1. 透過Git下載本教學課程的起始點:

    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/custom-component-start
    
  2. 使用Maven將程式碼基底部署至本機AEM例項:

    $ mvn clean install -PautoInstallSinglePackage
    

    如果使用AEM 6.x新增classic設定檔:

    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. 安裝傳統WKND參考站點的已完成包。 WKND參考站點提供的影像將在WKND SPA上重新使用。 可使用AEM套件管理器安裝套件。

    包管理器安裝wknd.all

您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/custom-component-solution在本機檢出程式碼。

定義AEM元件

AEM元件定義為節點和屬性。 在項目中,這些節點和屬性在ui.apps模組中以XML檔案的形式表示。 接下來,在ui.apps模組中建立AEM元件。

  1. 在所選IDE中,開啟ui.apps資料夾。

  2. 導覽至ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components並建立名為custom-component的新資料夾。

  3. custom-component資料夾下建立名為.content.xml的新檔案。 將下列項目填入custom-component/.content.xml:

    <?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:Component"
        jcr:title="Custom Component"
        componentGroup="WKND SPA Angular - Content"/>
    

    建立自訂元件定義

    jcr:primaryType="cq:Component" — 標識此節點將是AEM元件。

    jcr:title 是要顯示給內容作者的值,並決 componentGroup 定製作UI中的元件分組。

  4. custom-component資料夾下,建立另一個名為_cq_dialog的資料夾。

  5. _cq_dialog資料夾下方建立名為.content.xml的新檔案,並填入以下內容:

    <?xml version="1.0" encoding="UTF-8"?>
    <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:granite="http://www.adobe.com/jcr/granite/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
        jcr:primaryType="nt:unstructured"
        jcr:title="Custom Component"
        sling:resourceType="cq/gui/components/authoring/dialog">
        <content
            jcr:primaryType="nt:unstructured"
            sling:resourceType="granite/ui/components/coral/foundation/container">
            <items jcr:primaryType="nt:unstructured">
                <tabs
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/tabs"
                    maximized="{Boolean}true">
                    <items jcr:primaryType="nt:unstructured">
                        <properties
                            jcr:primaryType="nt:unstructured"
                            jcr:title="Properties"
                            sling:resourceType="granite/ui/components/coral/foundation/container"
                            margin="{Boolean}true">
                            <items jcr:primaryType="nt:unstructured">
                                <columns
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                                    margin="{Boolean}true">
                                    <items jcr:primaryType="nt:unstructured">
                                        <column
                                            jcr:primaryType="nt:unstructured"
                                            sling:resourceType="granite/ui/components/coral/foundation/container">
                                            <items jcr:primaryType="nt:unstructured">
                                                <message
                                                    jcr:primaryType="nt:unstructured"
                                                    sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
                                                    fieldDescription="The text to display on the component."
                                                    fieldLabel="Message"
                                                    name="./message"/>
                                            </items>
                                        </column>
                                    </items>
                                </columns>
                            </items>
                        </properties>
                    </items>
                </tabs>
            </items>
        </content>
    </jcr:root>
    

    自訂元件定義

    上面的XML檔案為Custom Component生成一個非常簡單的對話框。 檔案的關鍵部分是內部<message>節點。 此對話框將包含名為Message的簡單textfield,並將文本欄位的值保存到名為message的屬性。

    系統會在旁邊建立Sling模型,以透過JSON模型公開message屬性的值。

    注意

    您可以檢視核心元件定義🔗以檢視更多對話方塊範例。 您也可以檢視其他表單欄位,例如selecttextareapathfield,可在CRXDE-Lite/libs/granite/ui/components/coral/foundation/form下方取得。

    若使用傳統AEM元件,通常需要 HTL指令碼。 由於SPA會轉譯元件,因此不需要HTL指令碼。

建立Sling模型

Sling模型是註解導向的Java "POJO's"(純舊Java物件),可方便將資料從JCR對應至Java變數。 Sling Model 一般能封裝AEM元件的複雜伺服器端業務邏輯。

在SPA編輯器的內容中,Sling模型會透過使用Sling Model Exporter的功能,透過JSON模型公開元件的內容。

  1. 在所選IDE中,開啟core模組。 CustomComponent.javaCustomComponentImpl.java 已建立,並在章節起始程式碼中逐步運用。

    注意

    如果使用Visual Studio Code IDE,則安裝Java的擴展可能會很有幫助。

  2. core/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/CustomComponent.java開啟Java介面CustomComponent.java:

    CustomComponent.java介面

    這是Sling模型將實作的Java介面。

  3. 更新CustomComponent.java以便擴展ComponentExporter介面:

    package com.adobe.aem.guides.wknd.spa.angular.core.models;
    import com.adobe.cq.export.json.ComponentExporter;
    
    public interface CustomComponent extends ComponentExporter {
    
        public String getMessage();
    
    }
    

    實作ComponentExporter介面是JSON模型API自動擷取Sling模型的需求。

    CustomComponent介面包括單個getter方法getMessage()。 此方法會透過JSON模型公開製作對話方塊的值。 在JSON模型中,將僅導出空參數()的getter方法。

  4. core/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/impl/CustomComponentImpl.java開啟CustomComponentImpl.java

    這是CustomComponent介面的實現。 @Model注釋將Java類標識為Sling模型。 @Exporter注釋使Java類能夠通過Sling模型導出器進行序列化和導出。

  5. 更新靜態變數RESOURCE_TYPE以指向先前練習中建立的AEM元件wknd-spa-angular/components/custom-component

    static final String RESOURCE_TYPE = "wknd-spa-angular/components/custom-component";
    

    元件的資源類型將系結Sling Model至AEM元件,並最終對應至Angular元件。

  6. getExportedType()方法添加到CustomComponentImpl類以返回元件資源類型:

    @Override
    public String getExportedType() {
        return CustomComponentImpl.RESOURCE_TYPE;
    }
    

    實作ComponentExporter介面時需要此方法,它將公開允許映射到Angular元件的資源類型。

  7. 更新getMessage()方法以傳回由製作對話方塊保存的message屬性值。 使用@ValueMap注釋將JCR值message映射到Java變數:

    import org.apache.commons.lang3.StringUtils;
    ...
    
    @ValueMapValue
    private String message;
    
    @Override
    public String getMessage() {
        return StringUtils.isNotBlank(message) ? message.toUpperCase() : null;
    }
    

    新增一些額外的「業務邏輯」,以傳回訊息的值作為大寫。 這可讓我們查看製作對話方塊所儲存的原始值與Sling模型公開的值之間的差異。

    注意

    您可以在此處🔗查看已完成的CustomComponentImpl.java。

更新Angular元件

自訂元件的Angular程式碼已建立。 接下來,進行一些更新,將Angular元件對應至AEM元件。

  1. ui.frontend模組中開啟檔案ui.frontend/src/app/components/custom/custom.component.ts

  2. 觀察@Input() message: string;行。 預期轉換後的大寫值會對應至此變數。

  3. 從AEM SPA Editor JS SDK匯入MapTo物件,並使用它對應至AEM元件:

    + import {MapTo} from '@adobe/cq-angular-editable-components';
    
     ...
     export class CustomComponent implements OnInit {
         ...
     }
    
    + MapTo('wknd-spa-angular/components/custom-component')(CustomComponent, CustomEditConfig);
    
  4. 開啟cutom.component.html ,並觀察{{message}}的值將顯示在<h2>標籤的側邊。

  5. 開啟custom.component.css並新增下列規則:

    :host-context {
        display: block;
    }
    

    為了在元件為空時正確顯示AEM編輯器預留位置,:host-context或其他<div>必須設為display: block;

  6. 使用您的Maven技能,從專案目錄的根目錄,將所有更新部署至本機AEM環境:

    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    

更新模板策略

接下來,導覽至AEM以驗證更新並允許將Custom Component新增至SPA。

  1. 導覽至http://localhost:4502/system/console/status-slingmodels以驗證新Sling模型的註冊。

    com.adobe.aem.guides.wknd.spa.angular.core.models.impl.CustomComponentImpl - wknd-spa-angular/components/custom-component
    
    com.adobe.aem.guides.wknd.spa.angular.core.models.impl.CustomComponentImpl exports 'wknd-spa-angular/components/custom-component' with selector 'model' and extension '[Ljava.lang.String;@6fb4a693' with exporter 'jackson'
    

    您應會看到上述兩行,指出CustomComponentImplwknd-spa-angular/components/custom-component元件相關聯,且已透過Sling模型匯出工具註冊。

  2. 導覽至SPA頁面範本,網址為http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html

  3. 更新「配置容器」的策略,以將新Custom Component添加為允許的元件:

    更新佈局容器策略

    保存對策略的更改,並將Custom Component作為允許的元件進行觀察:

    自訂元件作為允許的元件

製作自訂元件

接下來,使用AEM SPA編輯器製作Custom Component

  1. 導覽至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html

  2. Edit模式中,將Custom Component新增至Layout Container:

    插入新元件

  3. 開啟元件的對話方塊,然後輸入包含某些小寫字母的訊息。

    設定自訂元件

    這是在章節前面根據XML檔案建立的對話框。

  4. 儲存變更。請注意,顯示的訊息會以所有大寫表示。

    全大寫顯示的訊息

  5. 導覽至http://localhost:4502/content/wknd-spa-angular/us/en.model.json以檢視JSON模型。 搜尋 wknd-spa-angular/components/custom-component:

    "custom_component_208183317": {
        "message": "HELLO WORLD",
        ":type": "wknd-spa-angular/components/custom-component"
    }
    

    請注意,JSON值會根據新增至Sling模型的邏輯而設為所有大寫字母。

恭喜!

恭喜您,您已學會如何建立自訂AEM元件,以及Sling模型和對話方塊如何與JSON模型搭配運作。

您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/custom-component-solution在本機檢出程式碼。

後續步驟

擴充核心元件 — 了解如何擴充現有核心元件以與AEM SPA編輯器搭配使用。了解如何將屬性和內容新增至現有元件,是擴充AEM SPA Editor實作功能的強大技術。

本頁內容