AEM Adobe experience Manager-扩展核心组件

背景

因为在做一个国际项目,架构师选择AEM进行开发,所以就学了一通。结果在做一个需求的时候遇到一个比较常见问题,就想着输出一篇文档记录一下。

需求背景就是:需要基于WCM(web content management)的核心组件自定义一个面包屑breadcrumb组件。 一般的套路就是自定义组件的.content.xml配置文件里的sling:resourceSuperType设置为核心组件的path。但是需求上说需要在原来Breadcrumb组件的Dialog弹窗增加一个textfield

需求难点

按上面说的,自定义组件利用resourceSuperType来复用核心组件Breadcrumb,之后再到组件的_cq_dialog的配置里面增加一个textfield的组件。这个配置不难。但是如何利用Sling将新增的textfield通过model返回出来 这个就有点懵了。

解决方式

因为要复用以及扩展组件,所以第一时间想到的就是继承。于是找到了Breadcrumb组件的实现类: BreadcrumbImpl,想当然的去继承这玩意,但是因为对Sling的原理不太清楚,继承之后增加getText()方法发现部署上去会报错:can't resolve model...后来找了个官方文档(见文章最后面的‘参考文章’)

具体实施

image

上面ui.apps 是自定义组件的配置项 ui.core是自定义组件model的定义

创建组件

按照上图,创建一个自定义组件,其中breadcrumb组件定义的.content.xml中要设置sling:resourceSuperType="core/wcm/components/breadcrumb/v1/breadcrumb" 指向需要被扩展的核心组件即可,具体配置如下

<?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"
          cq:icon="breadcrumbNavigation"
          jcr:description="Displays the position of the current page within the site hierarchy"
          sling:resourceSuperType="core/wcm/components/breadcrumb/v1/breadcrumb"
          jcr:primaryType="cq:Component"
          jcr:title="Breadcrumb Component"
          componentGroup="Custom Component"/>

继承/扩展组件Dialog

  1. 首先在自定义组件中创建_cq_dialog以及对应的.content.xml配置
  2. 直接在github上复制下breadcrumb的Dialog的.content.xml配置(地址:github-aem-core-wcm-components-breadcrumb
  3. 进行相应的改造
    3.1 使用sling:hideResource="{Boolean}true" 隐藏Dialog原有属性
    3.2 新增配置,使用 margin="true"
    3.3 可以复用的组件就不管,直接添加需要被新增的组件

以下为_cq_dialog详细配置

<?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" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
          jcr:description="Breadcrumb Dialog"
          jcr:primaryType="nt:unstructured"
          jcr:title="Breadcrumb"
          sling:resourceType="cq/gui/components/authoring/dialog"
          sling:hideProperties="id"
          helpPath="https://www.adobe.com/go/aem_cmp_breadcrumb_v1"
          trackingFeature="core-components:breadcrumb:v1">
    <content
            jcr:primaryType="nt:unstructured"
            margin="{Boolean}true"
            sling:resourceType="granite/ui/components/coral/foundation/tabs">
        <items jcr:primaryType="nt:unstructured">
		这里直接隐藏核心组件的fixedColums
            <fixedcolums
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"
                    sling:hideResource="{Boolean}true">
            </fixedcolums>
		这里显示自定义的配置(Dialog上一个叫properties的Tab)
            <properties
                    jcr:primaryType="nt:unstructured"
			<!--margin="true" 标识这里可以被扩展-->
                    margin="true"
                    sling:resourceType="granite/ui/components/coral/foundation/include"
                    path="/apps/tech-aem/components/common/breadcrumb/v1/breadcrumb/cq:dialog/properties"/>
        </items>
    </content>

    <properties jcr:primaryType="nt:unstructured"
                jcr:title="Properties"
                sling:resourceType="granite/ui/components/coral/foundation/container">
        <items jcr:primaryType="nt:unstructured">
            <fixedcolums
                    jcr:primaryType="nt:unstructured"
                    sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
                <items jcr:primaryType="nt:unstructured">
                    <properties
                            jcr:primaryType="nt:unstructured"
                            sling:resourceType="granite/ui/components/coral/foundation/container">
                        <items jcr:primaryType="nt:unstructured">
                            <startLevel
                                    jcr:primaryType="nt:unstructured"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/numberfield"
                                    fieldDescription="The level at which to start the breadcrumb: 0 = /content, 1 = /content/site, etc."
                                    fieldLabel="Navigation Start Level"
                                    max="100"
                                    min="1"
                                    name="./startLevel"
                                    step="1"
                                    value="2"/>
                            <backgroundColor
                                    jcr:primaryType="nt:unstructured"
                                    name="./backgroundColor"
                                    fieldLabel="Background Color"
                                    sling:resourceType="granite/ui/components/coral/foundation/form/select">
                                <items jcr:primaryType="nt:unstructured">
                                    <white jcr:primaryType="nt:unstructured"
                                           default="true"
                                           text="White"
                                           value="false"/>
                                    <grey jcr:primaryType="nt:unstructured"
                                          text="Grey"
                                          value="true"/>
                                </items>
                            </backgroundColor>
                        </items>
                    </properties>
                </items>
            </fixedcolums>
        </items>
    </properties>
</jcr:root>

继承/扩展组件Model

上面是前端组件的继承/扩展方式,接下来就是如何扩展核心组件的Model了, 参考下图
image

  1. 首先新建一个BreadcrumbModel(interface) 继承 Breadcrumb(interface) 核心组件
  2. BreadcrumbModel中定义新增的方法,这里因为是在dialog里面加了一个textfield,所以新增一个getText()方法
  3. 创建Sling的Model类:BreadcrumbComponent(类名随便)实现BreadcrumbModel和ComponentExporter这两个interface
  4. 在BreadcrumbComponent中实现BreadcrumbModel声明的方法
  5. 增加注解@Model,注意里面的adapters
@Model(adaptables = SlingHttpServletRequest.class,
        adapters = {BreadcrumbModel.class, ComponentExporter.class},
        resourceType = BreadcrumbComponent.RESOURCE_TYPE, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
@Exporter(name = "jackson", extensions = "json")
public class BreadcrumbComponent implements BreadcrumbModel, ComponentExporter {

    // 这里这个很关键,复用就用这个
    @Self
    @Via(type = ResourceSuperType.class)
    private Breadcrumb breadcrumb;

    public static final String RESOURCE_TYPE = "tech-aem/components/common/breadcrumb/v1/breadcrumb";

    @SlingObject
    private SlingHttpServletRequest request;

    @ValueMapValue
    private String text;

    public String getText() {
        return text;
    }

    @Override
    public Collection<NavigationItem> getItems() {
        return breadcrumb.getItems();
    }

}

然后加上package-info.java就大工告成了

结束语

可能会有点啰嗦,所以可以看下官方的文档是怎么个流程

参考文章

posted @ 2023-03-06 14:53  你啊347  阅读(148)  评论(0编辑  收藏  举报