将SPA组件映射到AEM组件 map-components

IMPORTANT
SPA 编辑器已被新项目弃用。Adobe 对现有项目仍提供支持,但不应在新项目中使用。目前,AEM 中用于管理 Headless 内容的首选编辑器是:

了解如何使用Angular SPA编辑器JS SDK将AEM组件映射到Adobe Experience Manager (AEM)组件。 组件映射使用户能够在AEM SPA编辑器中对SPA组件进行动态更新,类似于传统的AEM创作。

本章更深入地介绍了AEM JSON模型API,以及如何将由AEM组件公开的JSON内容作为prop自动插入到Angular组件中。

目标

  1. 了解如何将AEM组件映射到SPA组件。
  2. 了解​ Container ​组件与​ Content ​组件之间的区别。
  3. 创建映射到现有Angular组件的新AEM组件。

您将构建什么

本章将检查提供的Text SPA组件如何映射到AEM Text组件。 已创建新的Image SPA组件,该组件可在SPA中使用并在AEM中创作。 布局容器​和​ 模板编辑器 ​策略的开箱即用功能还将用于创建外观变化稍大的视图。

章节示例最终创作

先决条件

查看设置本地开发环境所需的工具和说明。

获取代码

  1. 通过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
    
  2. 使用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组件的高级概述

将AEM组件映射到Angular组件的高级概述

检查文本组件

AEM项目原型提供了一个映射到AEM 文本组件Text组件。 这是​ content ​组件的示例,该组件渲染来自AEM的​content

我们来看看组件的工作方式。

检查JSON模型

  1. 在介绍SPA代码之前,请务必了解AEM提供的JSON模型。 导航到核心组件库并查看文本组件的页面。 核心组件库提供了所有AEM核心组件的示例。

  2. 为以下示例之一选择​ JSON ​选项卡:

    文本JSON模型

    您应该看到三个属性:textrichText:type

    :type是一个保留属性,它列出了AEM组件的sling:resourceType(或路径)。 :type的值用于将AEM组件映射到SPA组件。

    textrichText是对SPA组件公开的其他属性。

检查文本组件

  1. 打开新终端并导航到项目中的ui.frontend文件夹。 运行npm install,然后运行npm start以启动​webpack开发服务器

    code language-shell
    $ cd ui.frontend
    $ npm run start:mock
    

    ui.frontend模块当前设置为使用模拟JSON模型

  2. 您应会看到一个新的浏览器窗口打开http://localhost:4200/content/wknd-spa-angular/us/en/home.html

    包含模拟内容的 Webpack开发服务器

  3. 在您选择的IDE中,打开WKND SPA的AEM项目。 展开ui.frontend模块并打开ui.frontend/src/app/components/text/text.component.ts下的文件​text.component.ts

    Text.js Angular组件Source代码

  4. 第一个要检查的区域是位于第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属性。

  5. 接下来,在~第24行检查TextEditConfig

    code language-js
    const TextEditConfig = {
        emptyLabel: 'Text',
        isEmpty: cqModel =>
            !cqModel || !cqModel.text || cqModel.text.trim().length < 1
    };
    

    上述代码负责确定何时在AEM创作环境中呈现占位符。 如果isEmpty方法返回​true,则会呈现占位符。

  6. 最后,查看第53行以下位置的MapTo调用:

    code language-js
    MapTo('wknd-spa-angular/components/text')(TextComponent, TextEditConfig );
    

    MapTo is provided by the 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找到AEM Text组件定义。

  7. 通过在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属性以查看正在运行的渲染逻辑。

  8. ui.frontend/src/app/components/text/text.component.html处检查​text.component.html

    此文件为空,因为组件的全部内容由innerHTML属性设置。

  9. ui.frontend/src/app/app.module.ts处检查​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 图像组件ImageAngular组件。 Image组件是​ content ​组件的另一个示例。

检查JSON

在跳转到SPA代码之前,请检查AEM提供的JSON模型。

  1. 导航到核心组件库🔗中的图像示例。

    图像核心组件JSON

    srcalttitle的属性用于填充SPA Image组件。

    note note
    NOTE
    其他公开的图像属性(lazyEnabledwidths)允许开发人员创建自适应和延迟加载组件。 The component built in this tutorial is simple and does not use these advanced properties.
  2. Return to your IDE and open up the en.model.json at ui.frontend/src/mocks/json/en.model.json. Since this is a net-new component for our project we need to "mock" the Image JSON.

    At ~line 70 add a JSON entry for the image model (don't forget about the trailing comma , after the second text_386303036) and update the :itemsOrder array.

    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"
            ],
    

    The project includes a sample image at /mock-content/adobestock-140634652.jpeg that is used with the webpack dev server.

    You can view the full en.model.json here.

  3. Add a stock photo to be displayed by the component.

    Create a new folder named images beneath ui.frontend/src/mocks. Download adobestock-140634652.jpeg and place it in the newly created images folder. Feel free to use your own image, if desired.

Implement the Image component

  1. Stop the webpack dev server if started.

  2. Create a new Image component by running the Angular CLI ng generate component command from within ui.frontend folder:

    code language-shell
    $ ng generate component components/image
    
  3. In the IDE, open image.component.ts at ui.frontend/src/app/components/image/image.component.ts and update as follows:

    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 is the configuration to determine whether to render the author placeholder in AEM, based on if the src property is populated.

    @Input() of src, alt, and title are the properties mapped from the JSON API.

    hasImage() is a method that will determine if the image should be rendered.

    MapTo maps the SPA component to the AEM component located at ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image.

  4. Open image.component.html and update it as follows:

    code language-html
    <ng-container *ngIf="hasImage">
        <img class="image" [src]="src" [alt]="alt" [title]="title"/>
    </ng-container>
    

    This will render the <img> element if hasImage returns true.

  5. Open image.component.scss and update it as follows:

    code language-scss
    :host-context {
        display: block;
    }
    
    .image {
        margin: 1rem 0;
        width: 100%;
        border: 0;
    }
    
    note note
    NOTE
    The :host-context rule is critical for the AEM SPA editor placeholder to function correctly. All SPA components that are intended to be authored in the AEM page editor will need this rule at a minimum.
  6. Open app.module.ts and add the ImageComponent to the entryComponents array:

    code language-js
    entryComponents: [TextComponent, PageComponent, ImageComponent],
    

    Like the TextComponent, the ImageComponent is dynamically loaded, and must be included in the entryComponents array.

  7. 启动​ webpack开发服务器 ​以查看ImageComponent渲染。

    code language-shell
    $ npm run start:mock
    

    图像已添加到模拟

    图像已添加到SPA

    note note
    NOTE
    附加质询:实施新方法以将title的值显示为图像下方的标题。

在AEM中更新策略

ImageComponent组件仅在​ webpack开发服务器 ​中可见。 接下来,将更新的SPA部署到AEM并更新模板策略。

  1. 停止​webpack开发服务器,并从项目的​ ​中,使用您的Maven技能将更改部署到AEM:

    code language-shell
    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
  2. 从AEM开始屏幕导航到​工具 > 模板 > WKND SPA Angular

    选择并编辑​SPA页面

    编辑SPA页面模板

  3. 选择​ 布局容器 ​并单击它的​ 策略 ​图标以编辑策略:

    布局容器策略

  4. 在​允许的组件 > WKND SPA Angular - Content >下,检查​ Image ​组件:

    已选择 图像组件

    在​默认组件 > 添加映射​下,并选择​ 图像 — WKND SPA Angular - Content ​组件:

    设置默认组件

    输入image/*的​MIME类型

    单击​ 完成 ​以保存策略更新。

  5. 在​ 布局容器 ​中,单击​ 文本 ​组件的​ 策略 ​图标:

    文本组件策略图标

    创建名为​ WKND SPA Text ​的新策略。 在​插件 > 格式 >下,选中所有框以启用其他格式选项:

    启用RTE格式

    在​插件 > 段落样式 >下,选中​ 启用段落样式 ​的框:

    启用段落样式

    单击​ 完成 ​以保存策略更新。

  6. 导航到​主页 http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html

    您还应该能够编辑Text组件并在​ 全屏 ​模式下添加其他段落样式。

    全屏富文本编辑

  7. 您还应该能够从​ 资产查找器 ​中拖放图像:

    拖放图像

  8. 通过AEM Assets添加您自己的映像,或者为标准WKND引用站点安装完成的代码库。 WKND引用站点包含可在WKND SPA上重复使用的许多图像。 可以使用AEM的包管理器安装该包。

    包管理器安装wknd.all

检查布局容器

AEM SPA编辑器SDK自动提供对​ 布局容器 ​的支持。 名称指示的​ 布局容器 ​是​ 容器 ​组件。 容器组件是接受JSON结构的组件,该结构表示​ 其他 ​组件并动态实例化它们。

让我们进一步检查布局容器。

  1. 在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包含在项目中。

  2. 在浏览器中导航到http://localhost:4502/content/wknd-spa-angular/us/en.model.json

    JSON模型API — 响应式网格

    布局容器​组件具有wcm/foundation/components/responsivegridsling:resourceType,SPA编辑器使用:type属性识别它,就像TextImage组件一样。

    在SPA编辑器中,可以使用布局模式重新调整组件大小的相同功能。

  3. 返回至http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html。 添加其他​ 图像 ​组件,然后尝试使用​ 布局 ​选项重新调整其大小:

    使用布局模式重新调整图像大小

  4. 重新打开JSON模型http://localhost:4502/content/wknd-spa-angular/us/en.model.json,并观察作为JSON一部分的columnClassNames

    列类名

    类名aem-GridColumn--default--4指示组件应基于12列网格为4列宽。 有关响应式网格的更多详细信息见此处

  5. 返回到IDE,在ui.apps模块中ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/clientlibs/clientlib-grid处定义了客户端库。 打开文件 less/grid.less

    此文件确定​ 布局容器 ​使用的断点(defaulttabletphone)。 此文件将根据项目规范进行自定义。 当前断点设置为1200px650px

  6. 您应该能够使用Text组件的响应式功能和更新的富文本策略来创作类似于以下内容的视图:

    章节示例最终创作

恭喜! congratulations

恭喜,您已了解如何将SPA组件映射到AEM组件,并且实施了新的Image组件。 您还有机会探索​ 布局容器 ​的响应式功能。

您始终可以在GitHub上查看完成的代码,或通过切换到分支Angular/map-components-solution在本地签出代码。

后续步骤 next-steps

导航和路由 — 了解如何使用SPA Editor SDK映射到AEM Pages,从而支持SPA中的多个视图。 动态导航是使用Angular路由器实现的,并添加到现有的报头组件中。

额外练习 — 将配置保留到源代码管理 bonus

在许多情况下,尤其是在AEM项目开始时,将配置(如模板和相关内容策略)保留到源代码控制中很有价值。 这可确保所有开发人员都针对同一组内容和配置工作,额外确保环境之间的一致性。 只要项目达到了一定的成熟度,管理模板的实践工作就可以移交给一个专门的高级用户组。

接下来的几个步骤将使用Visual Studio Code IDE和VSCode AEM Sync执行,但可以使用任何工具和您已配置为从AEM的本地实例​ 提取 ​或​ 导入 ​内容的任何IDE执行。

  1. 在Visual Studio Code IDE中,确保已通过Marketplace扩展安装​VSCode AEM Sync

    VSCode AEM同步

  2. 在项目资源管理器中展开​ ui.content ​模块并导航到/conf/wknd-spa-angular/settings/wcm/templates

  3. 右键单击 templates 文件夹,然后选择​从 AEM 服务器导入

    VSCode 导入模板

  4. 重复导入内容的步骤,但选择位于/conf/wknd-spa-angular/settings/wcm/policies的​ 策略 ​文件夹。

  5. 检查位于ui.content/src/main/content/META-INF/vault/filter.xmlfilter.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.xmlui.apps/src/main/content/META-INF/vault/filter.xml,了解每个模块管理的不同节点。

recommendation-more-help
e25b6834-e87f-4ff3-ba56-4cd16cdfdec4