扩展核心组件 extend-component

了解如何扩展要与AEM SPA编辑器一起使用的现有核心组件。 了解如何扩展现有组件是一种强大的技术,可用于自定义和扩展AEM SPA Editor实施的功能。

目标

  1. 使用其他属性和内容扩展现有核心组件。
  2. 通过使用了解组件继承的基本知识 sling:resourceSuperType.
  3. 了解如何使用 委派模式 以便Sling模型重复使用现有逻辑和功能。

您将构建的内容

在本章中,将介绍 Card 组件已创建。 此 Card 组件扩展 图像核心组件 添加其他内容字段,如“标题”和“行动号召”按钮,为SPA中的其他内容执行Teaser角色。

卡组件的最终创作

NOTE
在实际实施中,可能更适合简单地使用 Teaser组件 比扩展 图像核心组件 以制作 Card 组件,具体取决于项目要求。 建议始终使用 核心组件 可能时直接发送。

前提条件

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

获取代码

  1. 通过Git下载本教程的起点:

    code language-shell
    $ git clone git@github.com:adobe/aem-guides-wknd-spa.git
    $ cd aem-guides-wknd-spa
    $ git checkout Angular/extend-component-start
    
  2. 使用Maven将代码库部署到本地AEM实例:

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage
    

    如果使用 AEM 6.x 添加 classic 个人资料:

    code language-shell
    $ mvn clean install -PautoInstallSinglePackage -Pclassic
    
  3. 为传统安装完成的包 WKND引用站点. 图片提供方: WKND引用站点 在WKND SPA上重用。 可使用以下方式安装软件包 AEM包管理器.

    包管理器安装wknd.all

您始终可以在上查看完成的代码 GitHub 或者切换到分支机构在本地签出代码 Angular/extend-component-solution.

Inspect初始卡实施

章节起始代码提供了初始卡组件。 Inspect是信息卡实施的起点。

  1. 在您选择的IDE中,打开 ui.apps 模块。

  2. 导航到 ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/card 并查看 .content.xml 文件。

    卡组件AEM定义开始

    code language-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图像组件的功能。

  3. Inspect文件 ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/image/.content.xml

    code language-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图像组件继承了核心组件图像的功能。

    也称为 代理模式 Sling资源继承是一种强大的设计模式,它允许子组件继承功能并在需要时扩展/覆盖行为。 Sling继承支持多个级别的继承,因此最终将支持新的 Card 组件继承核心组件图像的功能。

    许多开发团队都努力做到自我(不要重复自己)。 Sling继承使得在AEM中可以做到这一点。

  4. card 文件夹,打开文件 _cq_dialog/.content.xml.

    此文件是组件对话框定义 Card 组件。 如果使用Sling继承,则可以使用的 Sling资源合并器 覆盖或扩展对话框的各个部分。 在此示例中,向对话框添加了一个新选项卡,用于从作者捕获其他数据以填充卡组件。

    属性,如 sling:orderBefore 允许开发人员选择插入新选项卡或表单字段的位置。 在本例中, Text 选项卡插入在 asset 选项卡。 为了充分利用Sling资源合并器,了解 图像组件对话框.

  5. card 文件夹,打开文件 _cq_editConfig.xml. 此文件指示AEM创作UI中的拖放行为。 扩展图像组件时,资源类型必须与组件本身匹配,这一点很重要。 查看 <parameters> 节点:

    code language-xml
    <parameters
        jcr:primaryType="nt:unstructured"
        sling:resourceType="wknd-spa-angular/components/card"
        imageCrop=""
        imageMap=""
        imageRotate=""/>
    

    大多数组件不需要 cq:editConfig、图像和图像组件的子后代是例外。

  6. 在IDE中,切换到 ui.frontend 模块,导航到 ui.frontend/src/app/components/card

    angular组件启动

  7. Inspect文件 card.component.ts.

    该组件已被清除以映射到AEM Card 使用标准的组件 MapTo 函数。

    code language-js
    MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);
    

    查看三个 @Input 的类中的参数 srcalt、和 title. 这些是AEM组件中映射到Angular组件的JSON值。

  8. 打开文件 card.component.html

    code language-html
    <div class="card"  *ngIf="hasContent">
        <app-image class="card__image" [src]="src" [alt]="alt" [title]="title"></app-image>
    </div>
    

    在此示例中,我们选择重用现有的Angular图像组件 app-image 只需传递 @Input 参数来源 card.component.ts. 稍后,在本教程中添加和显示了其他属性。

更新模板策略

使用此初始 Card 实施审查AEM SPA编辑器中的功能。 要查看初始 Card 组件需要更新模板策略。

  1. 将起始代码部署到AEM的本地实例(如果尚未部署):

    code language-shell
    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
  2. 导航至SPA页面模板,网址为 http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.

  3. 更新布局容器的策略以添加新的 Card 组件作为允许的组件:

    更新布局容器策略

    保存对策略所做的更改,并观察 Card 组件作为允许的组件:

    将卡组件作为允许的组件

创作初始卡组件

接下来,创作 Card 组件使用AEM SPA编辑器。

  1. 导航到 http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.

  2. Edit 模式,添加 Card 组件到 Layout Container

    插入新组件

  3. 将图像从资产查找器拖放到 Card 组件:

    添加图像

  4. 打开 Card “组件”对话框,并注意添加了 文本 选项卡。

  5. 请在以下位置输入以下值 文本 选项卡:

    “文本组件”选项卡

    信息卡路径 — 在SPA主页下选择页面。

    CTA文本 — “了解更多”

    卡片标题 — 留空

    从链接的页面获取标题 — 选中复选框以指示true。

  6. 更新 资源元数据 制表符添加值 替换文本题注.

    更新对话框后,当前未显示其他更改。 要将新字段公开给Angular组件,我们需要更新的Sling模型 Card 组件。

  7. 打开新选项卡并导航到 CRXDE-Lite. Inspect下的内容节点 /content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegrid 以查找 Card 组件内容。

    CRXDE-Lite组件属性

    观察该属性 cardPathctaTexttitleFromPage 对话框将持久保留。

更新卡片Sling模型

要最终将组件对话框中的值显示给Angular组件,我们需要更新填充的JSON的Sling模型 Card 组件。 我们还有机会实施两种业务逻辑:

  • 如果 titleFromPagetrue,返回由指定的页面的标题 cardPath 否则,返回值 cardTitle 文本字段。
  • 返回由指定的页的上次修改日期 cardPath.

返回您选择的IDE并打开 core 模块。

  1. 打开文件 Card.javacore/src/main/java/com/adobe/aem/guides/wknd/spa/angular/core/models/Card.java.

    请注意, Card 接口当前扩展 com.adobe.cq.wcm.core.components.models.Image 因此继承了 Image 界面。 此 Image 接口已扩展 ComponentExporter 接口,通过该接口可将Sling模型导出为JSON并由SPA编辑器进行映射。 因此,我们不需要显式扩展 ComponentExporter 界面,就像我们在 自定义组件章节.

  2. 将以下方法添加到接口:

    code language-java
    @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组件。

  3. 打开 CardImpl.java. 这是的实施 Card.java 界面。 为加速教程,已部分修剪此实施。 请注意, @Model@Exporter 注释,以确保能够通过Sling模型导出器将Sling模型序列化为JSON。

    CardImpl.java 也使用 Sling模型的委托模式 避免重写图像核心组件中的逻辑。

  4. 请注意以下行:

    code language-java
    @Self
    @Via(type = ResourceSuperType.class)
    private Image image;
    

    上述注释实例化一个名为的图像对象 image 基于 sling:resourceSuperType 的继承 Card 组件。

    code language-java
    @Override
    public String getSrc() {
        return null != image ? image.getSrc() : null;
    }
    

    然后,可以简单地使用 image 用于实施由定义的方法的对象 Image 界面,无需自己编写逻辑。 此技术用于 getSrc()getAlt()、和 getTitle().

  5. 接下来,实施 initModel() 用于启动私有变量的方法 cardPage 基于的值 cardPath

    code language-java
    @PostConstruct
    public void initModel() {
        if(StringUtils.isNotBlank(cardPath) && pageManager != null) {
            cardPage = pageManager.getPage(this.cardPath);
        }
    }
    

    @PostConstruct initModel() Sling模型初始化时调用,因此可以借此机会初始化模型中其他方法可能使用的对象。 此 pageManager 是多个之一 Java™支持的全局对象 可供Sling模型使用,具体方式如下: @ScriptVariable 注释。 此 getPage 方法接收路径并返回AEM 页面 对象,如果路径未指向有效页面,则为null。

    这会初始化 cardPage 变量,其他新方法使用该变量返回有关底层链接页面的数据。

  6. 查看已映射到JCR属性的全局变量,该属性保存了“作者”对话框。 此 @ValueMapValue 注释用于自动执行映射。

    code language-java
    @ValueMapValue
    private String cardPath;
    
    @ValueMapValue
    private String ctaText;
    
    @ValueMapValue
    private boolean titleFromPage;
    
    @ValueMapValue
    private String cardTitle;
    

    这些变量用于实现的其他方法 Card.java 界面。

  7. 实施中定义的其他方法 Card.java 界面:

    code language-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;
    }
    
    note note
    NOTE
    您可以查看 在此处完成CardImpl.java.
  8. 打开终端窗口,将更新仅部署到 core 模块使用Maven autoInstallBundle 配置文件来自 core 目录。

    code language-shell
    $ cd core/
    $ mvn clean install -PautoInstallBundle
    

    如果使用 AEM 6.x 添加 classic 个人资料。

  9. 在以下位置查看JSON模型响应: http://localhost:4502/content/wknd-spa-angular/us/en.model.json 并搜索 wknd-spa-angular/components/card

    code language-json
    "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"
    }
    

    请注意,在更新中的方法后,将使用其他键/值对更新JSON模型 CardImpl Sling模型。

更新Angular组件

现在,JSON模型已为 ctaLinkURLctaTextcardTitle、和 cardLastModified 我们可以更新Angular组件以显示这些内容。

  1. 返回到IDE并打开 ui.frontend 模块。 (可选)从新终端窗口启动webpack开发服务器以实时查看更改:

    code language-shell
    $ cd ui.frontend
    $ npm install
    $ npm start
    
  2. 打开 card.component.tsui.frontend/src/app/components/card/card.component.ts. 添加其他 @Input 用于捕获新模型的注释:

    code language-diff
    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;
    
  3. 添加用于检查行动号召是否准备就绪以及根据 cardLastModified 输入:

    code language-js
    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;
        }
        ...
    }
    
  4. 打开 card.component.html 并添加以下标记以显示标题、行动要求和上次修改日期:

    code language-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>
    

    已在添加Sass规则 card.component.scss 要设置标题的样式,请行动要求和上次修改日期。

    note note
    NOTE
    您可以查看完成的 在此处Angular卡组件代码.
  5. 使用Maven从项目的根目录部署对AEM的完整更改:

    code language-shell
    $ cd aem-guides-wknd-spa
    $ mvn clean install -PautoInstallSinglePackage
    
  6. 导航到 http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html 要查看更新的组件,请执行以下操作:

    更新了AEM中的卡组件

  7. 您应该能够重新创作现有内容以创建类似于以下内容的页面:

    卡组件的最终创作

恭喜! congratulations

恭喜,您已了解如何扩展AEM组件以及Sling模型和对话框如何与JSON模型一起使用。

您始终可以在上查看完成的代码 GitHub 或者切换到分支机构在本地签出代码 Angular/extend-component-solution.

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