將SPA元件對應至AEM元件 map-components
瞭解如何使用AEM SPA Editor JS SDK將Angular元件對應至Adobe Experience Manager (AEM)元件。 元件對應可讓使用者在SPA SPA編輯器中對AEM元件進行動態更新,類似於傳統的AEM編寫。
本章更深入地探討AEM JSON模型API,以及如何將AEM元件公開的JSON內容作為prop自動插入到Angular元件中。
目標
- 瞭解如何將AEM元件對應至SPA元件。
- 瞭解 Container 元件與 Content 元件之間的差異。
- 建立對應至現有AEM元件的新Angular元件。
您將建置的內容
本章將檢查提供的Text
SPA元件如何對應至AEM Text
元件。 已建立可在SPA中使用並在AEM中編寫的新Image
SPA元件。 配置容器 和 範本編輯器 原則的現成功能也會用來建立外觀稍有變化的檢視。
先決條件
檢閱設定本機開發環境所需的工具和指示。
取得程式碼
-
透過Git下載本教學課程的起點:
code language-shell $ git clone git@github.com:adobe/aem-guides-wknd-spa.git $ cd aem-guides-wknd-spa $ git checkout Angular/map-components-start
-
使用Maven將程式碼庫部署到本機AEM執行個體:
code language-shell $ mvn clean install -PautoInstallSinglePackage
如果使用AEM 6.x,請新增
classic
設定檔:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/map-components-solution
在本機取出程式碼。
對應方法
基本概念是對應SPA元件至AEM元件。 AEM元件,執行伺服器端,將內容匯出為JSON模型API的一部分。 SPA會使用JSON內容,在瀏覽器中執行使用者端。 SPA元件和AEM元件之間會建立1:1對應。
將AEM元件對應到Angular元件的高階概觀
Inspect文字元件
AEM專案原型提供對應至AEM 文字元件的Text
元件。 這是 content 元件的範例,它從AEM轉譯 內容。
讓我們瞭解元件的運作方式。
Inspect JSON模型
-
在跳入SPA程式碼之前,請務必瞭解AEM提供的JSON模型。 導覽至核心元件庫,並檢視文字元件的頁面。 核心元件庫提供所有AEM核心元件的範例。
-
選取其中一個範例的 JSON 標籤:
您應該會看到三個屬性:
text
、richText
和:type
。:type
是保留屬性,列出AEM元件的sling:resourceType
(或路徑)。:type
的值是用來將AEM元件對應到SPA元件的值。text
和richText
是公開給SPA元件的其他屬性。
Inspect文字元件
-
開啟新的終端機,並導覽至專案內的
ui.frontend
資料夾。 執行npm install
,然後執行npm start
以啟動 webpack開發伺服器:code language-shell $ cd ui.frontend $ npm run start:mock
ui.frontend
模組目前設定為使用模擬JSON模型。 -
您應該會看到新的瀏覽器視窗開啟到http://localhost:4200/content/wknd-spa-angular/us/en/home.html
含有模擬內容的
-
在您選擇的IDE中,開啟WKND SPA的AEM專案。 展開
ui.frontend
模組並開啟ui.frontend/src/app/components/text/text.component.ts
下的檔案 text.component.ts: -
第一個要檢查的區域是位於~第35行的
class TextComponent
:code language-js export class TextComponent { @Input() richText: boolean; @Input() text: string; @Input() itemName: string; @HostBinding('innerHtml') get content() { return this.richText ? this.sanitizer.bypassSecurityTrustHtml(this.text) : this.text; } @HostBinding('attr.data-rte-editelement') editAttribute = true; constructor(private sanitizer: DomSanitizer) {} }
@Input()裝飾器可用來宣告欄位,這些欄位的值是透過先前已檢閱的對應JSON物件設定的。
@HostBinding('innerHtml') get content()
是從this.text
的值公開所編寫文字內容的方法。 在內容為RTF文字的情況下(由this.richText
標幟決定),會略過Angular的內建安全性。 angular的DomSanitizer用來「清除」原始HTML並防止跨網站指令碼漏洞。 方法已使用@HostBinding裝飾程式繫結至innerHtml
屬性。 -
接著在~第24行檢查
TextEditConfig
:code language-js const TextEditConfig = { emptyLabel: 'Text', isEmpty: cqModel => !cqModel || !cqModel.text || cqModel.text.trim().length < 1 };
上述程式碼負責決定何時在AEM製作環境中呈現預留位置。 如果
isEmpty
方法傳回 true,則會轉譯預留位置。 -
最後檢視位於~行53的
MapTo
呼叫:code language-js MapTo('wknd-spa-angular/components/text')(TextComponent, TextEditConfig );
MapTo 由AEM SPA Editor JS SDK (
@adobe/cq-angular-editable-components
)提供。 路徑wknd-spa-angular/components/text
代表AEM元件的sling:resourceType
。 此路徑與先前觀察到的JSON模型公開的:type
相符。 MapTo 會剖析JSON模型回應,並將正確的值傳遞至SPA元件的@Input()
變數。您可以在
ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/text
找到AEMText
元件定義。 -
修改
ui.frontend/src/mocks/json/en.model.json
的 en.model.json 檔案以進行實驗。在~第62行,更新前
Text
個值以使用H1
和u
標籤:code language-json "text": { "text": "<h1><u>Hello World!</u></h1>", "richText": true, ":type": "wknd-spa-angular/components/text" }
返回瀏覽器以檢視 webpack開發伺服器 所提供的效果:
請嘗試在 true / false 之間切換
richText
屬性,以檢視執行中的轉譯器邏輯。 -
Inspect text.component.html 於
ui.frontend/src/app/components/text/text.component.html
。此檔案是空的,因為元件的整個內容是由
innerHTML
屬性所設定。 -
在
ui.frontend/src/app/app.module.ts
的 app.module.ts Inspect。code language-js @NgModule({ imports: [ BrowserModule, SpaAngularEditableComponentsModule, AppRoutingModule ], providers: [ModelManagerService, { provide: APP_BASE_HREF, useValue: '/' }], declarations: [AppComponent, TextComponent, PageComponent, HeaderComponent], entryComponents: [TextComponent, PageComponent], bootstrap: [AppComponent] }) export class AppModule {}
未明確包含 TextComponent,而是透過AEM SPA編輯器JS SDK提供的 AEMResponsiveGridComponent 動態包含。 因此,必須列在 app.module.ts' entryComponents陣列中。
建立影像元件
接著,建立對應至AEM Image元件的Image
Angular元件。 Image
元件是 content 元件的另一個範例。
Inspect和JSON
在跳入SPA程式碼之前,請檢查AEM提供的JSON模型。
-
導覽至核心元件庫🔗中的影像範例。
src
、alt
和title
的屬性是用來填入SPAImage
元件。note note NOTE 有其他公開的影像屬性( lazyEnabled
,widths
)可讓開發人員建立最適化且延遲載入的元件。 此教學課程中建置的元件非常簡單,不會 使用這些進階屬性。 -
返回您的IDE並在
ui.frontend/src/mocks/json/en.model.json
開啟en.model.json
。 由於這是我們專案的全新元件,因此需要「模擬」影像JSON。在~第70行,為
image
模型新增JSON專案(別忘了第二個text_386303036
之後的尾端逗號,
)並更新:itemsOrder
陣列。code language-json ... ":items": { ... "text_386303036": { "text": "<p>A new text component.</p>\r\n", "richText": true, ":type": "wknd-spa-angular/components/text" }, "image": { "alt": "Rock Climber in New Zealand", "title": "Rock Climber in New Zealand", "src": "/mocks/images/adobestock-140634652.jpeg", ":type": "wknd-spa-angular/components/image" } }, ":itemsOrder": [ "text", "text_386303036", "image" ],
專案在
/mock-content/adobestock-140634652.jpeg
包含搭配 webpack開發伺服器 使用的範例影像。您可以在🔗檢視完整的en.model.json。
-
新增元件要顯示的庫存像片。
在
ui.frontend/src/mocks
下建立名為 影像 的新資料夾。 下載adobestock-140634652.jpeg並將其放入新建立的 影像 資料夾。 您可視需要使用自己的影像。
實作影像元件
-
如果啟動,請停止 webpack dev server。
-
從
ui.frontend
資料夾中執行AngularCLIng generate component
命令,以建立新的影像元件:code language-shell $ ng generate component components/image
-
在IDE中,開啟位於
ui.frontend/src/app/components/image/image.component.ts
的 image.component.ts,並依照以下方式更新:code language-js import {Component, Input, OnInit} from '@angular/core'; import {MapTo} from '@adobe/cq-angular-editable-components'; const ImageEditConfig = { emptyLabel: 'Image', isEmpty: cqModel => !cqModel || !cqModel.src || cqModel.src.trim().length < 1 }; @Component({ selector: 'app-image', templateUrl: './image.component.html', styleUrls: ['./image.component.scss'] }) export class ImageComponent implements OnInit { @Input() src: string; @Input() alt: string; @Input() title: string; constructor() { } get hasImage() { return this.src && this.src.trim().length > 0; } ngOnInit() { } } MapTo('wknd-spa-angular/components/image')(ImageComponent, ImageEditConfig);
ImageEditConfig
是決定是否在AEM中根據src
屬性是否填入來轉譯作者預留位置的設定。src
、alt
和title
中的@Input()
為從JSON API對應的屬性。hasImage()
是將決定是否應呈現影像的方法。MapTo
將SPA元件對應至位於ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image
的AEM元件。 -
開啟 image.component.html 並依照以下方式更新:
code language-html <ng-container *ngIf="hasImage"> <img class="image" [src]="src" [alt]="alt" [title]="title"/> </ng-container>
如果
hasImage
傳回 true,這會轉譯<img>
元素。 -
開啟 image.component.scss 並依照以下方式更新:
code language-scss :host-context { display: block; } .image { margin: 1rem 0; width: 100%; border: 0; }
note note NOTE :host-context
規則是 關鍵,AEM SPA編輯器預留位置才能正常運作。 打算在SPA頁面編輯器中編寫的所有AEM元件至少需要此規則。 -
開啟
app.module.ts
並將ImageComponent
新增至entryComponents
陣列:code language-js entryComponents: [TextComponent, PageComponent, ImageComponent],
與
TextComponent
一樣,ImageComponent
也是動態載入,必須包含在entryComponents
陣列中。 -
啟動 webpack開發伺服器 以檢視
ImageComponent
轉譯器。code language-shell $ npm run start:mock
影像已新增至SPA
note note NOTE 附加挑戰:實作新方法以將 title
的值顯示為影像下方的標題。
在AEM中更新原則
ImageComponent
元件僅顯示在 webpack開發伺服器 中。 接下來,將更新的SPA部署到AEM並更新範本原則。
-
停止 webpack開發伺服器,並從專案的 根 使用您的Maven技能將變更部署到AEM:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage
-
從AEM開始畫面導覽至 工具 > 範本 > WKND SPAAngular。
選取並編輯 SPA頁面:
-
選取 配置容器,然後按一下它的 原則 圖示以編輯原則:
-
在 允許的元件 > WKND SPAAngular — 內容 >檢查 影像 元件下:
已選取
在 預設元件 > 新增對應 下,並選擇 影像 — WKND SPAAngular- Content 元件:
輸入
image/*
的 mime型別。按一下 完成 以儲存原則更新。
-
在 配置容器 中,按一下 文字 元件的 原則 圖示:
建立名稱為 WKND SPA Text 的新原則。 在 外掛程式 > 格式 >核取所有方塊以啟用其他格式選項:
在 外掛程式 > 段落樣式 >下方,勾選方塊以 啟用段落樣式:
按一下 完成 以儲存原則更新。
-
瀏覽至 首頁 http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。
您也應該能夠編輯
Text
元件,並在 全熒幕 模式中新增其他段落樣式。 -
您也應該能夠從 資產尋找器 拖放影像:
-
透過AEM Assets新增您自己的影像,或安裝標準WKND參考網站完成的程式碼基底。 WKND參考網站包含許多可在WKND SPA上重複使用的影像。 可以使用AEM封裝管理員來安裝封裝。
Inspect配置容器
AEM SPA編輯器SDK會自動提供對 配置容器 的支援。 名稱所指示的 配置容器 是 容器 元件。 容器元件是接受JSON結構的元件,這些結構代表 其他 個元件並動態具現化它們。
讓我們進一步檢查配置容器。
-
在IDE中,在
ui.frontend/src/app/components/responsive-grid
開啟 responsive-grid.component.ts:code language-js import { AEMResponsiveGridComponent,MapTo } from '@adobe/cq-angular-editable-components'; MapTo('wcm/foundation/components/responsivegrid')(AEMResponsiveGridComponent);
AEMResponsiveGridComponent
已實作為AEM SPA Editor SDK的一部分,並透過import-components
包含在專案中。 -
在瀏覽器中導覽至http://localhost:4502/content/wknd-spa-angular/us/en.model.json
配置容器 元件有
wcm/foundation/components/responsivegrid
的sling:resourceType
,而且可由SPA編輯器使用:type
屬性來辨識,就像Text
和Image
元件一樣。SPA編輯器也提供使用配置模式重新調整元件大小的相同功能。
-
返回http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。 新增其他 影像 元件,然後嘗試使用 配置 選項重新調整其大小:
-
重新開啟JSON模型http://localhost:4502/content/wknd-spa-angular/us/en.model.json,並觀察作為JSON一部分的
columnClassNames
:類別名稱
aem-GridColumn--default--4
表示元件應以12欄格線為4欄寬。 如需回應式格線的詳細資訊,請參閱此處。 -
返回IDE,在
ui.apps
模組中有一個在ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-grid
定義的使用者端程式庫。 開啟檔案less/grid.less
。此檔案決定 配置容器 使用的中斷點(
default
、tablet
和phone
)。 此檔案旨在根據專案規格自訂。 目前中斷點設定為1200px
和650px
。 -
您應該能夠使用
Text
元件的回應式功能和更新的RTF原則來編寫如下的檢視:
恭喜! congratulations
恭喜,您已瞭解如何將SPA元件對應至AEM元件,並且已實作新的Image
元件。 您也有機會探索 配置容器 的回應式功能。
您一律可以在GitHub上檢視完成的程式碼,或切換至分支Angular/map-components-solution
在本機取出程式碼。
後續步驟 next-steps
導覽及路由 — 瞭解如何使用SPA編輯器SDK對應至AEM頁面,以支援SPA中的多個檢視。 動態導覽是使用Angular路由器實作,並新增至現有的Header元件。
額外優點 — 將設定保留到原始檔控制 bonus
在許多情況下,尤其是在AEM專案開始時,將設定(例如範本和相關內容原則)保留到原始檔控制中很有價值。 這可確保所有開發人員都針對相同的內容和設定集,且可確保環境之間有額外的一致性。 一旦專案達到一定的成熟度,管理範本的實務就可以交給特殊的超級使用者群組。
後續幾個步驟將使用Visual Studio Code IDE和VSCode AEM Sync進行,但可能會使用任何工具和您已設定為從AEM本機執行個體 提取 或 匯入 內容的任何IDE來執行。
-
在Visual Studio Code IDE中,確定您已透過Marketplace擴充功能安裝 VSCode AEM Sync:
-
展開專案總管中的 ui.content 模組,並導覽至
/conf/wknd-spa-angular/settings/wcm/templates
。 -
按一下滑鼠右鍵
templates
資料夾並選取 從AEM伺服器匯入: -
重複步驟以匯入內容,但選取位於
/conf/wknd-spa-angular/settings/wcm/policies
的 原則 資料夾。 -
Inspect位於
ui.content/src/main/content/META-INF/vault/filter.xml
的filter.xml
檔案。code language-xml <!--ui.content filter.xml--> <?xml version="1.0" encoding="UTF-8"?> <workspaceFilter version="1.0"> <filter root="/conf/wknd-spa-angular" mode="merge"/> <filter root="/content/wknd-spa-angular" mode="merge"/> <filter root="/content/dam/wknd-spa-angular" mode="merge"/> <filter root="/content/experience-fragments/wknd-spa-angular" mode="merge"/> </workspaceFilter>
filter.xml
檔案負責識別隨套件安裝的節點路徑。 請注意每個篩選器上的mode="merge"
,這表示現有內容將不會被修改,只會新增內容。 由於內容作者可能正在更新這些路徑,因此程式碼部署 不會 覆寫內容非常重要。 請參閱FileVault檔案,以取得使用篩選元素的詳細資訊。比較
ui.content/src/main/content/META-INF/vault/filter.xml
與ui.apps/src/main/content/META-INF/vault/filter.xml
,瞭解每個模組所管理的不同節點。