自定义AEM CIF核心组件 customize-cif-components

CIF Venia项目是使用CIF核心组件的参考代码库。 在本教程中,您进一步扩展了Product Teaser组件以显示Adobe Commerce中的自定义属性。 您还可以详细了解AEM与Adobe Commerce之间的GraphQL集成以及CIF核心组件提供的扩展挂接。

TIP
在启动您自己的商务实现时使用AEM项目原型

您将构建的内容

Venia品牌最近开始使用可持续材料制造一些产品,并且公司希望在Product Teaser中显示​ 环保徽章。 在Adobe Commerce中创建一个新的自定义属性,以指示产品是否使用​ 环保材料。 此自定义属性作为GraphQL查询的一部分添加,并显示在指定产品的产品Teaser中。

环保徽章最终实施

先决条件 prerequisites

需要本地开发环境才能完成本教程。 此环境包括一个正在运行的AEM实例,该实例已配置并连接到Adobe Commerce实例。 查看使用AEM as a Cloud Service SDK设置本地开发的要求和步骤。 要完全遵循本教程,您需要具有在Adobe Commerce中将属性添加到产品的权限。

您还需要GraphQL IDE(如GraphiQL)或浏览器扩展来运行代码示例和教程。 如果安装浏览器扩展,请确保可以设置请求标头。 在Google Chrome上,Altair GraphQL Client ​是一个可执行此作业的扩展。

克隆Venia项目 clone-venia-project

克隆Venia项目,然后覆盖默认样式。

NOTE
请随时使用现有项目(基于包含CIF的AEM项目原型)并跳过此部分。
  1. 运行以下git命令,以便克隆项目:

    code language-shell
    $ git clone git@github.com:adobe/aem-cif-guides-venia.git
    
  2. 生成项目并将其部署到AEM的本地实例:

    code language-shell
    $ cd aem-cif-guides-venia/
    $ mvn clean install -PautoInstallSinglePackage,cloud
    
  3. 添加必要的OSGi配置,以便将AEM实例连接到Adobe Commerce实例,或将配置添加到创建的项目。

  4. 此时,您应该拥有连接到Adobe Commerce实例的工作中店面版本。 导航至US > Home页面,网址为: http://localhost:4502/editor.html/content/venia/us/en.html

    您应该会看到店面当前使用的是Venia主题。 展开店面的主菜单,您应该会看到各种类别,这表示与Adobe Commerce的连接正在正常工作。

    店面配置了Venia主题

创作产品Teaser author-product-teaser

本教程中对产品Teaser组件进行了扩展。 第一步,向主页添加Product Teaser的实例以了解基线功能。

  1. 导航到网站的​ 主页http://localhost:4502/editor.html/content/acme/us/en.html

  2. 将新的​ Product Teaser ​组件插入页面上的主布局容器中。

    插入产品Teaser

  3. 展开侧面板(如果尚未切换)并将资产查找器下拉列表切换到​ 产品。 此列表应显示连接的Adobe Commerce实例中可用产品的列表。 选择一个产品并​ 将其拖放 ​到页面上的​ Product Teaser ​组件上。

    拖放产品Teaser

    note note
    NOTE
    请注意,您还可以通过使用对话框(单击​_扳手_​图标)配置组件来配置显示的产品。
  4. 此时,您应该会看到产品Teaser正在显示产品。 产品名称和产品价格是显示的默认属性。

    产品Teaser — 默认样式

在Adobe Commerce中添加自定义属性 add-custom-attribute

AEM中显示的产品和产品数据存储在Adobe Commerce中。 接下来,使用Adobe Commerce UI将​ 环保特性 ​添加为产品特性集的一部分。

TIP
产品属性集中已有自定义​ 是/否 ​属性? 欢迎您随时使用,并跳过此部分。
  1. 登录到您的Adobe Commerce实例。

  2. 导航到​ 目录 > 产品

  3. 更新搜索筛选器,以便您可以找到在上一个练习添加到Teaser组件时使用的​ 可配置产品。 在编辑模式下打开产品。

    搜索Valeria产品

  4. 在产品视图中,单击​ 添加属性 > 创建新属性

  5. 使用以下值填写​ 新属性 ​表单(保留其他值的默认设置)

    table 0-row-3 1-row-3 2-row-3 3-row-3
    字段集 字段标签 价值
    属性属性 属性标签 环保
    属性属性 目录输入类型 是/否
    高级属性属性 属性代码 环保

    新属性表单

    完成后,单击​ 保存属性

  6. 滚动到产品底部并展开​ 属性 ​标题。 您应该会看到新的​ 环保型 ​字段。 将切换开关切换到​

    切换到“是”

    保存 ​对产品的更改。

    note tip
    TIP
    有关管理产品属性的更多详细信息,请参阅Adobe Commerce用户指南
  7. 导航到​ 系统 > 工具 > 缓存管理。 由于对数据架构进行了更新,因此您必须使Adobe Commerce中的某些缓存类型失效。

  8. 选中​ 配置 ​旁边的框并提交​ 刷新 ​的缓存类型

    刷新配置缓存类型

    note tip
    TIP
    有关缓存管理的更多详细信息,请参阅Adobe Commerce用户指南

使用GraphQL IDE验证属性 use-graphql-ide

在跳转到AEM代码之前,使用GraphQL IDE浏览GraphQL概述会很有用。 Adobe Commerce与AEM的集成主要通过一系列GraphQL查询来完成。 了解和修改GraphQL查询是扩展CIF核心组件的关键方式之一。

接下来,使用GraphQL IDE验证是否已将eco_friendly属性添加到产品属性集。 本教程中的屏幕截图使用的是​ Altair GraphQL Client Google Chrome扩展。

  1. 打开GraphQL IDE,然后在IDE或扩展的URL栏中输入URL http://<commerce-server>/graphql

  2. 添加以下产品查询,其中YOUR_SKU是上一个练习中使用的产品的​ SKU

    code language-json
      {
        products(
        filter: { sku: { eq: "YOUR_SKU" } }
        ) {
            items {
            name
            sku
            eco_friendly
            }
        }
    }
    
  3. 执行查询,您应会收到如下响应:

    code language-json
    {
      "data": {
        "products": {
          "items": [
            {
              "name": "Valeria Two-Layer Tank",
              "sku": "VT11",
              "eco_friendly": 1
            }
          ]
        }
      }
    }
    

    示例GraphQL响应

    Yes ​的值是​ 1 ​的整数。 当您使用Java™编写GraphQL查询时,该值很有用。

    note tip
    TIP
    有关详细信息,请参阅Adobe Commerce GraphQL

更新产品Teaser的Sling模型 updating-sling-model-product-teaser

接下来,通过实施Sling模型来扩展Product Teaser的业务逻辑。 Sling模型是注释驱动的“POJO”(纯旧Java™对象),它们实现组件所需的业务逻辑。 Sling模型与HTL脚本一起用作组件的一部分。 遵循Sling模型🔗的委派模式,以便您可以扩展现有产品Teaser模型的部分。

Sling模型是作为Java™实现的,并且可在所生成项目的​ core ​模块中找到。

使用您选择的IDE导入Venia项目。 使用的屏幕截图来自Visual Studio Code IDE

  1. 在IDE中的​ core ​模块下导航到: core/src/main/java/com/venia/core/models/commerce/MyProductTeaser.java

    核心位置IDE

    MyProductTeaser.java是扩展CIF ProductTeaser接口的Java™接口。

    已添加名为isShowBadge()的新方法以显示徽章(如果产品被视为“新”)。

  2. isEcoFriendly()添加到接口:

    code language-java
    @ProviderType
    public interface MyProductTeaser extends ProductTeaser {
        // Extend the existing interface with the additional properties which you
        // want to expose to the HTL template.
        public Boolean isShowBadge();
    
        public Boolean isEcoFriendly();
    }
    

    引入此新方法以封装逻辑以指示产品的eco_friendly属性是否设置为​ ​或​

  3. 接下来,在core/src/main/java/com/venia/core/models/commerce/MyProductTeaserImpl.java处检查MyProductTeaserImpl.java

    Sling模型🔗的委托模式允许MyProductTeaserImpl通过sling:resourceSuperType属性引用ProductTeaser模型:

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

    对于您不想覆盖或更改的方法,您可以返回ProductTeaser返回的值。 例如:

    code language-java
    @Override
    public String getImage() {
        return productTeaser.getImage();
    }
    

    此方法可最大限度地减少实施必须编写的Java™代码量。

  4. AEM CIF核心组件提供的额外扩展点之一是AbstractProductRetriever,它提供对特定产品属性的访问权限。 Inspect initModel()方法:

    code language-java
    import javax.annotation.PostConstruct;
    ...
    @Model(adaptables = SlingHttpServletRequest.class, adapters = MyProductTeaser.class, resourceType = MyProductTeaserImpl.RESOURCE_TYPE)
    public class MyProductTeaserImpl implements MyProductTeaser {
        ...
        private AbstractProductRetriever productRetriever;
    
        /* add this method to initialize the productRetriever */
        @PostConstruct
        public void initModel() {
            productRetriever = productTeaser.getProductRetriever();
    
            if (productRetriever != null) {
                productRetriever.extendProductQueryWith(p -> p.createdAt());
            }
    
        }
    ...
    

    @PostConstruct注释可确保在Sling模型初始化时调用此方法。

    请注意,产品GraphQL查询已使用extendProductQueryWith方法扩展,以检索额外的created_at属性。 此属性稍后将用作isShowBadge()方法的一部分。

  5. 更新GraphQL查询以将eco_friendly属性包含在部分查询中:

    code language-java
    //MyProductTeaserImpl.java
    
    private static final String ECO_FRIENDLY_ATTRIBUTE = "eco_friendly";
    
    @PostConstruct
    public void initModel() {
        productRetriever = productTeaser.getProductRetriever();
    
        if (productRetriever != null) {
            productRetriever.extendProductQueryWith(p -> p
                .createdAt()
                .addCustomSimpleField(ECO_FRIENDLY_ATTRIBUTE)
            );
        }
    }
    

    将添加到extendProductQueryWith方法是确保其他产品属性可用于模型的其余部分的一种有效方法。 它还可以最大限度地减少执行的查询数。

    在上述代码中,addCustomSimpleField用于检索eco_friendly属性。 此属性说明了如何查询属于Adobe Commerce架构的任何自定义属性。

    note note
    NOTE
    createdAt()方法已作为产品接口的一部分实现。 大多数常见的架构属性都已实现,因此仅将addCustomSimpleField用于真正的自定义属性。
  6. 添加记录器以便调试Java™代码:

    code language-java
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    ...
    @Model(adaptables = SlingHttpServletRequest.class, adapters = MyProductTeaser.class, resourceType = MyProductTeaserImpl.RESOURCE_TYPE)
    public class MyProductTeaserImpl implements MyProductTeaser {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(MyProductTeaserImpl.class);
    
  7. 接下来,实现isEcoFriendly()方法:

    code language-java
    @Override
    public Boolean isEcoFriendly() {
    
        Integer ecoFriendlyValue;
        try {
            ecoFriendlyValue = productRetriever.fetchProduct().getAsInteger(ECO_FRIENDLY_ATTRIBUTE);
            if(ecoFriendlyValue != null && ecoFriendlyValue.equals(Integer.valueOf(1))) {
                LOGGER.info("*** Product is Eco Friendly**");
                return true;
            }
        } catch (SchemaViolationError e) {
            LOGGER.error("Error retrieving eco friendly attribute");
        }
        LOGGER.info("*** Product is not Eco Friendly**");
        return false;
    }
    

    在上述方法中,productRetriever用于获取产品,getAsInteger()方法用于获取eco_friendly属性的值。 根据您之前运行的GraphQL查询,您知道eco_friendly属性设置为“”时的预期值实际上是​ 1 ​的整数。

    现在Sling模型已更新,必须更新组件标记,以根据Sling模型实际显示​ 生态友好 ​指示器。

自定义产品Teaser的标记 customize-markup-product-teaser

AEM组件的常见扩展是修改组件生成的标记。 此编辑通过覆盖组件用于呈现其标记的HTL脚本来完成。 HTML模板语言(HTL)是一种轻量级模板语言,AEM组件使用它根据创作的内容动态呈现标记,从而允许组件重用。 例如,产品Teaser可以重复使用以显示不同的产品。

在本例中,您希望在Teaser顶部呈现横幅,以表明产品基于自定义属性是“环保的”。 自定义组件的标记的设计模式是所有AEM组件的标准模式,而不仅仅是AEM CIF核心组件的标准模式。

NOTE
如果您使用CIF产品和类别选取器(如此Product Teaser或CIF页面组件)自定义组件,请确保为组件对话框包含所需的cif.shell.picker clientlib。 有关详细信息,请参阅CIF产品和类别选取器的用法
  1. 在IDE中,导航并展开ui.apps模块,然后将文件夹层次结构展开到: ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productteaser并检查.content.xml文件。

    产品Teaser ui.apps

    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:description="Product Teaser Component"
        jcr:primaryType="cq:Component"
        jcr:title="Product Teaser"
        sling:resourceSuperType="core/cif/components/commerce/productteaser/v1/productteaser"
        componentGroup="Venia - Commerce"/>
    

    上面的组件定义适用于项目中的产品Teaser组件。 注意属性sling:resourceSuperType="core/cif/components/commerce/productteaser/v1/productteaser"。 此属性是创建代理组件的示例。 您可以使用sling:resourceSuperType继承所有功能,而不是从AEM CIF核心组件复制和粘贴产品Teaser HTL脚本。

  2. 打开文件productteaser.html。 此文件是CIF Product Teaser中的productteaser.html文件的副本。

    code language-html
    <!--/* productteaser.html */-->
    <sly
      data-sly-use.product="com.venia.core.models.commerce.MyProductTeaser"
      data-sly-use.templates="core/wcm/components/commons/v1/templates.html"
      data-sly-use.actionsTpl="actions.html"
      data-sly-test.isConfigured="${properties.selection}"
      data-sly-test.hasProduct="${product.url}"
    ></sly>
    

    请注意,已使用MyProductTeaser的Sling模型并将其分配给product变量。

  3. 修改productteaser.html,以便调用上一个练习中实现的isEcoFriendly方法:

    code language-html
    ...
    <div
      data-sly-test="${isConfigured && hasProduct}"
      class="item__root"
      data-cmp-is="productteaser"
      data-virtual="${product.virtualProduct}"
    >
      <div data-sly-test="${product.showBadge}" class="item__badge">
        <span>${properties.text || 'New'}</span>
      </div>
      <!--/* Insert call to Eco Friendly here */-->
      <div data-sly-test="${product.ecoFriendly}" class="item__eco">
        <span>Eco Friendly</span>
      </div>
      ...
    </div>
    

    在HTL中调用Sling模型方法时,该方法的getis部分将被丢弃,且第一个字母变为小写。 因此,isShowBadge()变为.showBadgeisEcoFriendly变为.ecoFriendly。 基于.isEcoFriendly()返回的布尔值,确定是否显示<span>Eco Friendly</span>

    有关data-sly-test和其他HTL块语句的详细信息,请参阅HTL规范

  4. 使用您的Maven技能从命令行终端保存更改并将更新部署到AEM:

    code language-shell
    $ cd aem-cif-guides-venia/
    $ mvn clean install -PautoInstallSinglePackage,cloud
    
  5. 打开新的浏览器窗口并导航到AEM和​ OSGi控制台 > 状态 > Sling模型http://localhost:4502/system/console/status-slingmodels

  6. 搜索MyProductTeaserImpl,您应该会看到如下所示的一行:

    code language-plain
    com.venia.core.models.commerce.MyProductTeaserImpl - venia/components/commerce/productteaser
    

    此行指示Sling模型已正确部署并映射到正确的组件。

  7. 刷新到​ Venia主页,该主页位于http://localhost:4502/editor.html/content/venia/us/en.html,其中已添加产品Teaser。

    显示 环保消息

    如果产品的eco_friendly属性设置为​ ,则您应该会在页面上看到文本“Eco Friendly”。 尝试切换到其他产品以查看行为变化。

  8. 接下来,打开AEM error.log以查看添加的log语句。 error.log位于<AEM SDK Install Location>/crx-quickstart/logs/error.log

    搜索AEM日志以查看Sling模型中添加的log语句:

    code language-plain
    2020-08-28 12:57:03.114 INFO [com.venia.core.models.commerce.MyProductTeaserImpl] *** Product is Eco Friendly**
    ...
    2020-08-28 13:01:00.271 INFO [com.venia.core.models.commerce.MyProductTeaserImpl] *** Product is not Eco Friendly**
    ...
    
    note caution
    CAUTION
    如果Teaser中使用的产品不将eco_friendly属性作为其属性集的一部分,则您还可能会看到一些栈栈跟踪。

为环保徽章添加样式 add-styles

此时,何时显示​ 环保徽章 ​徽章的逻辑正在工作,但纯文本可以使用某些样式。 接下来,向ui.frontend模块添加图标和样式以完成实施。

  1. 下载eco_friendly.svg文件。 此文件用作​ 环保的 ​徽章。

  2. 返回到IDE并导航到ui.frontend文件夹。

  3. eco_friendly.svg文件添加到ui.frontend/src/main/resources/images文件夹:

    已添加环保SVG

  4. ui.frontend/src/main/styles/commerce/_productteaser.scss处打开文件productteaser.scss

  5. .productteaser类中添加以下Sass规则:

    code language-scss
    .productteaser {
        ...
        .item__eco {
            width: 60px;
            height: 60px;
            left: 0px;
            overflow: hidden;
            position: absolute;
            padding: 5px;
    
        span {
            display: block;
            position: absolute;
            width: 45px;
            height: 45px;
            text-indent: -9999px;
            background: no-repeat center center url('../resources/images/eco_friendly.svg');
            }
        }
    ...
    }
    
    note note
    NOTE
    有关前端工作流的更多详细信息,请参阅设置CIF核心组件的样式
  6. 使用您的Maven技能从命令行终端保存更改并将更新部署到AEM:

    code language-shell
    $ cd aem-cif-guides-venia/
    $ mvn clean install -PautoInstallSinglePackage,cloud
    
  7. 刷新到​ Venia主页,该主页位于http://localhost:4502/editor.html/content/venia/us/en.html,其中已添加产品Teaser。

    环保徽章最终实施

恭喜 congratulations

您自定义了您的第一个AEM CIF组件! 您可以在此下载解决方案文件

奖励质询 bonus-challenge

查看已在产品Teaser中实施的​ New ​徽章的功能。 尝试添加额外的复选框以便作者控制何时应显示​ 环保型 ​徽章。 更新位于ui.apps/src/main/content/jcr_root/apps/venia/components/commerce/productteaser/_cq_dialog/.content.xml的组件对话框。

新徽章实施挑战

其他资源 additional-resources

recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab