了解如何擴充現有的核心元件以與AEM SPA編輯器搭配使用。 了解如何擴充現有元件是自訂和擴充AEM SPA Editor實作功能的強大技術。
sling:resourceSuperType
了解元件繼承的基本內容。本章將建立新的Card
元件。 Card
元件將擴展影像核心元件添加諸如「標題」和「呼叫操作」按鈕等其他內容欄位,以對SPA內的其他內容執行預告的角色。
查看設定本地開發環境所需的工具和說明。
透過Git下載本教學課程的起始點:
$ git clone git@github.com:adobe/aem-guides-wknd-spa.git
$ cd aem-guides-wknd-spa
$ git checkout Angular/extend-component-start
使用Maven將程式碼基底部署至本機AEM例項:
$ mvn clean install -PautoInstallSinglePackage
如果使用AEM 6.x新增classic
設定檔:
$ mvn clean install -PautoInstallSinglePackage -Pclassic
安裝傳統WKND參考站點的已完成包。 WKND參考站點提供的影像將在WKND SPA上重新使用。 可使用AEM套件管理器安裝套件。
您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/extend-component-solution
在本機檢出程式碼。
章節啟動程式代碼已提供初始卡元件。 Inspect是卡片實作的起點。
在所選IDE中,開啟ui.apps
模組。
導覽至ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/card
並檢視.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="Card"
sling:resourceSuperType="wknd-spa-angular/components/image"
componentGroup="WKND SPA Angular - Content"/>
屬性sling:resourceSuperType
指向wknd-spa-angular/components/image
,指示Card
元件將繼承WKND SPA Image元件的所有功能。
Inspect檔案ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image/.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="Image"
sling:resourceSuperType="core/wcm/components/image/v2/image"
componentGroup="WKND SPA Angular - Content"/>
請注意,sling:resourceSuperType
指向core/wcm/components/image/v2/image
。 這表示WKND SPA Image元件繼承核心元件映像的所有功能。
也稱為Proxy模式 Sling資源繼承是功能強大的設計模式,可讓子元件視需要繼承功能和擴充/覆寫行為。 Sling繼承支援多個繼承層級,因此新Card
元件最終會繼承核心元件影像的功能。
許多開發團隊努力成為DRY(別重複)。 Sling繼承讓AEM成為可能。
在card
資料夾下,開啟檔案_cq_dialog/.content.xml
。
此檔案是Card
元件的「元件對話框」定義。 如果使用Sling繼承,則可能使用Sling Resource Merger的功能來覆寫或延伸對話方塊的部分。 在此範例中,對話方塊已新增一個索引標籤,以從作者擷取其他資料以填入「卡片元件」。
sling:orderBefore
等屬性可讓開發人員選擇插入新索引標籤或表單欄位的位置。 在這種情況下, Text
標籤將插入在asset
標籤之前。 要充分利用Sling Resource Merger,請務必了解影像元件對話方塊的原始對話節點結構。
在card
資料夾下,開啟檔案_cq_editConfig.xml
。 此檔案會指定AEM製作UI中的拖放行為。 擴充影像元件時,資源類型必須符合元件本身。 查看<parameters>
節點:
<parameters
jcr:primaryType="nt:unstructured"
sling:resourceType="wknd-spa-angular/components/card"
imageCrop=""
imageMap=""
imageRotate=""/>
大多數元件不需要cq:editConfig
,影像元件的影像和子代是例外。
在IDE交換機中,導航至ui.frontend/src/app/components/card
模組:ui.frontend
Inspect檔案card.component.ts
。
已使用標準MapTo
函式將元件映射到AEM Card
元件。
MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);
查看類中src
、alt
和title
的三個@Input
參數。 這些是AEM元件中應對應至Angular元件的JSON值。
開啟檔案card.component.html
:
<div class="card" *ngIf="hasContent">
<app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image>
</div>
在此範例中,我們選取僅從card.component.ts
傳遞@Input
參數,以重新使用現有的Angular影像元件app-image
。 在稍後的教學課程中,將新增並顯示其他屬性。
透過此初始Card
實作,檢閱AEM SPA Editor中的功能。 要查看初始Card
元件,需要更新模板策略。
將入門程式碼部署至AEM的本機執行個體(如果尚未部署):
$ cd aem-guides-wknd-spa
$ mvn clean install -PautoInstallSinglePackage
導覽至SPA頁面範本,網址為http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html。
更新「配置容器」的策略,以將新Card
元件添加為允許的元件:
保存對策略的更改,並將Card
元件作為允許的元件進行觀察:
接下來,使用AEM SPA編輯器編寫Card
元件。
導覽至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。
在Edit
模式中,將Card
元件添加到Layout Container
:
從資產尋找器將影像拖放至Card
元件:
開啟Card
元件對話方塊,並注意Text索引標籤的新增。
在Text標籤上輸入以下值:
卡片路徑 — 在SPA首頁下方選擇頁面。
CTA文字 - 「了解詳情」
卡片標題 — 留空
從連結的頁面取得標題 — 勾選核取方塊以指出true。
更新資產中繼資料標籤以新增替代文字和註解的值。
目前,在更新對話方塊後,不會顯示其他變更。 若要將新欄位公開給Angular元件,我們需要更新Card
元件的Sling模型。
開啟新索引標籤,並導覽至CRXDE-Lite。 Inspect /content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegrid
下方的內容節點,以尋找Card
元件內容。
請注意,對話方塊會保存屬性cardPath
、ctaText
、titleFromPage
。
若要最終將元件對話方塊中的值公開給Angular元件,我們需要更新填入Card
元件JSON的Sling模型。 我們還有機會實施兩個業務邏輯:
titleFromPage
變為true,則傳回cardPath
所指定頁面的標題,否則傳回cardTitle
文字欄位的值。cardPath
所指定頁面的上次修改日期。返回您選擇的IDE並開啟core
模組。
在core/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/Card.java
開啟檔案Card.java
。
請注意,Card
介面當前擴展com.adobe.cq.wcm.core.components.models.Image
,因此繼承Image
介面的所有方法。 Image
介面已延伸ComponentExporter
介面,讓Sling模型可匯出為JSON,並由SPA編輯器對應。 因此,我們不需要像在自訂元件章節中所做的那樣顯式擴展ComponentExporter
介面。
將下列方法新增至介面:
@ProviderType
public interface Card extends Image {
/***
* The URL to populate the CTA button as part of the card.
* The link should be based on the cardPath property that points to a page.
* @return String URL
*/
public String getCtaLinkURL();
/***
* The text to display on the CTA button of the card.
* @return String CTA text
*/
public String getCtaText();
/***
* The date to be displayed as part of the card.
* This is based on the last modified date of the page specified by the cardPath
* @return
*/
public Calendar getCardLastModified();
/**
* Return the title of the page specified by cardPath if `titleFromPage` is set to true.
* Otherwise return the value of `cardTitle`
* @return
*/
public String getCardTitle();
}
這些方法會透過JSON模型API公開,並傳遞至Angular元件。
開啟 CardImpl.java
. 這是Card.java
介面的實現。 為加速本教學課程,本實作已做部分研究。 請注意使用@Model
和@Exporter
註解,以確保Sling模型能透過Sling模型匯出工具序列化為JSON。
CardImpl.java
也會使用 Sling模型的委 派模式,以避免從影像核心元件重新寫入所有邏輯。
請觀察下列行:
@Self
@Via(type = ResourceSuperType.class)
private Image image;
上述批注將根據Card
元件的sling:resourceSuperType
繼承來實例化名為image
的影像對象。
@Override
public String getSrc() {
return null != image ? image.getSrc() : null;
}
然後,只需使用image
對象來實現由Image
介面定義的方法,而無需自行編寫邏輯。 此技術用於getSrc()
、getAlt()
和getTitle()
。
接下來,實作initModel()
方法,以根據cardPath
的值啟動專用變數cardPage
@PostConstruct
public void initModel() {
if(StringUtils.isNotBlank(cardPath) && pageManager != null) {
cardPage = pageManager.getPage(this.cardPath);
}
}
初始化Sling模型時,一律會呼叫@PostConstruct initModel()
,因此,這是初始化模型中其他方法可能使用的物件的良機。 pageManager
是透過@ScriptVariable
註解可供Sling模型使用的數個Java支援的全域物件之一。 getPage方法會進入路徑並傳回AEM Page物件,若路徑未指向有效頁面,則傳回null。
這會初始化cardPage
變數,其他新方法將使用該變數來傳回基礎連結頁面的相關資料。
檢閱已對應至已儲存製作對話方塊之JCR屬性的全域變數。 @ValueMapValue
注釋用於自動執行映射。
@ValueMapValue
private String cardPath;
@ValueMapValue
private String ctaText;
@ValueMapValue
private boolean titleFromPage;
@ValueMapValue
private String cardTitle;
這些變數將用於實作Card.java
介面的其他方法。
實作Card.java
介面中定義的其他方法:
@Override
public String getCtaLinkURL() {
if(cardPage != null) {
return cardPage.getPath() + ".html";
}
return null;
}
@Override
public String getCtaText() {
return ctaText;
}
@Override
public Calendar getCardLastModified() {
if(cardPage != null) {
return cardPage.getLastModified();
}
return null;
}
@Override
public String getCardTitle() {
if(titleFromPage) {
return cardPage != null ? cardPage.getTitle() : null;
}
return cardTitle;
}
您可以在此處🔗檢視已完成的CardImpl.java。
開啟終端機視窗,使用core
目錄中的Maven autoInstallBundle
設定檔,只部署core
模組的更新。
$ cd core/
$ mvn clean install -PautoInstallBundle
如果使用AEM 6.x ,請新增classic
設定檔。
請在下列網址檢視JSON模型回應:http://localhost:4502/content/wknd-spa-angular/us/en.model.json並搜尋wknd-spa-angular/components/card
:
"card": {
"ctaText": "Read More",
"cardTitle": "Page 1",
"title": "Woman chillaxing with river views in Australian bushland",
"src": "/content/wknd-spa-angular/us/en/home/_jcr_content/root/responsivegrid/card.coreimg.jpeg/1595190732886/adobestock-216674449.jpeg",
"alt": "Female sitting on a large rock relaxing in afternoon dappled light the Australian bushland with views over the river",
"cardLastModified": 1591360492414,
"ctaLinkURL": "/content/wknd-spa-angular/us/en/home/page-1.html",
":type": "wknd-spa-angular/components/card"
}
請注意,在CardImpl
Sling模型中更新方法後,JSON模型已更新為其他索引鍵/值組。
現在,JSON模型已填入ctaLinkURL
、ctaText
、cardTitle
和cardLastModified
的新屬性,我們可以更新Angular元件以顯示這些屬性。
返回IDE並開啟ui.frontend
模組。 (可選)從新的終端窗口啟動Webpack開發伺服器,以即時查看更改:
$ cd ui.frontend
$ npm install
$ npm start
在ui.frontend/src/app/components/card/card.component.ts
開啟card.component.ts
。 添加附加的@Input
注釋以捕獲新模型:
export class CardComponent implements OnInit {
@Input() src: string;
@Input() alt: string;
@Input() title: string;
+ @Input() cardTitle: string;
+ @Input() cardLastModified: number;
+ @Input() ctaLinkURL: string;
+ @Input() ctaText: string;
新增方法,以檢查動作呼叫是否已就緒,並根據cardLastModified
輸入傳回日期/時間字串:
export class CardComponent implements OnInit {
...
get hasCTA(): boolean {
return this.ctaLinkURL && this.ctaLinkURL.trim().length > 0 && this.ctaText && this.ctaText.trim().length > 0;
}
get lastModifiedDate(): string {
const lastModifiedDate = this.cardLastModified ? new Date(this.cardLastModified) : null;
if (lastModifiedDate) {
return lastModifiedDate.toLocaleDateString();
}
return null;
}
...
}
開啟card.component.html
並新增下列標籤以顯示標題、動作呼叫和上次修改日期:
<div class="card" *ngIf="hasContent">
<app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image>
<div class="card__content">
<h2 class="card__title">
{{cardTitle}}
<span class="card__lastmod" *ngIf="lastModifiedDate">{{lastModifiedDate}}</span>
</h2>
<div class="card__action-container" *ngIf="hasCTA">
<a [routerLink]="ctaLinkURL" class="card__action-link" [title]="ctaText">
{{ctaText}}
</a>
</div>
</div>
</div>
已在card.component.scss
新增Sass規則,以設定標題、動作呼叫和上次修改日期的樣式。
您可以在此處🔗檢視已完成的Angular卡元件代碼。
使用Maven從專案的根目錄部署完整變更至AEM:
$ cd aem-guides-wknd-spa
$ mvn clean install -PautoInstallSinglePackage
導覽至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html以查看更新的元件:
您應該可以重新編寫現有內容,以建立類似下列的頁面:
恭喜您,您已學會如何使用擴充AEM元件,以及Sling模型和對話方塊如何與JSON模型搭配運作。
您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/extend-component-solution
在本機檢出程式碼。