将SPA组件映射到AEM组件 map-components
了解如何使用AEM SPA编辑器JS SDK将Angular组件映射到Adobe Experience Manager (AEM)组件。 组件映射使用户能够对AEM SPA编辑器中的SPA组件进行动态更新,这与传统AEM创作类似。
本章更深入地介绍了AEM JSON模型API,以及如何将由AEM组件公开的JSON内容作为prop自动插入到Angular组件中。
目标
- 了解如何将AEM组件映射到SPA组件。
- 了解 Container 组件与 Content 组件之间的区别。
- 创建映射到现有AEM组件的新Angular组件。
您将构建的内容
本章将检查提供的Text
SPA组件如何映射到AEM Text
组件。 已创建可在SPA中使用并在SPA中创作的新Image
AEM组件。 布局容器 和 模板编辑器 策略的开箱即用功能还将用于创建外观变化稍大的视图。
先决条件
查看设置本地开发环境所需的工具和说明。
获取代码
-
通过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的一部分。 JSON内容由SPA使用,在浏览器中运行客户端。 在SPA组件和AEM组件之间创建1:1映射。
将AEM组件映射到Angular组件的高级概述
Inspect文本组件
AEM项目原型提供了一个映射到AEM 文本组件的Text
组件。 这是 content 组件的示例,该组件渲染来自AEM的 content。
我们来看看组件的工作方式。
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
的值中公开所编写的文本内容的方法。 如果内容是富文本(由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编辑器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
上Inspect app.module.ts。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
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并将其放入新创建的 images 文件夹中。 如果需要,您可以随意使用您自己的图像。
实施图像组件
-
如果启动,请停止 webpack开发服务器。
-
通过从
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
是一种配置,用于根据是否填充了src
属性确定是否在AEM中呈现作者占位符。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
组件的响应式功能和更新的富文本策略来创作类似于以下内容的视图:
恭喜! congratulations
恭喜,您已了解如何将SPA组件映射到AEM组件,并且实施了新的Image
组件。 您还有机会探索 布局容器 的响应式功能。
您始终可以在GitHub上查看完成的代码,或通过切换到分支Angular/map-components-solution
在本地签出代码。
后续步骤 next-steps
导航和路由 — 了解如何使用SPA编辑器SDK映射到AEM页面,从而支持SPA中的多个视图。 动态导航使用Angular路由器实现,并添加到现有的报头组件中。
额外练习 — 将配置保留到源代码管理 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
以了解每个模块管理的不同节点。