扩展核心组件 extend-component
了解如何扩展要与AEM SPA编辑器一起使用的现有核心组件。 了解如何扩展现有组件是一种强大的技术,可用于自定义和扩展AEM SPA Editor实施的功能。
目标
- 使用其他属性和内容扩展现有核心组件。
- 通过使用了解组件继承的基本知识
sling:resourceSuperType
. - 了解如何使用 委派模式 以便Sling模型重复使用现有逻辑和功能。
您将构建的内容
在本章中,将介绍 Card
组件已创建。 此 Card
组件扩展 图像核心组件 添加其他内容字段,如“标题”和“行动号召”按钮,为SPA中的其他内容执行Teaser角色。
前提条件
查看所需的工具和设置说明 本地开发环境.
获取代码
-
通过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
-
使用Maven将代码库部署到本地AEM实例:
code language-shell $ mvn clean install -PautoInstallSinglePackage
如果使用 AEM 6.x 添加
classic
个人资料:code language-shell $ mvn clean install -PautoInstallSinglePackage -Pclassic
-
为传统安装完成的包 WKND引用站点. 图片提供方: WKND引用站点 在WKND SPA上重用。 可使用以下方式安装软件包 AEM包管理器.
您始终可以在上查看完成的代码 GitHub 或者切换到分支机构在本地签出代码 Angular/extend-component-solution
.
Inspect初始卡实施
章节起始代码提供了初始卡组件。 Inspect是信息卡实施的起点。
-
在您选择的IDE中,打开
ui.apps
模块。 -
导航到
ui.apps/src/main/content/jcr_root/apps/wknd-spa-angular/components/card
并查看.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="Card" sling:resourceSuperType="wknd-spa-angular/components/image" componentGroup="WKND SPA Angular - Content"/>
属性
sling:resourceSuperType
指向wknd-spa-angular/components/image
指示Card
组件继承了WKND SPA图像组件的功能。 -
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中可以做到这一点。
-
在
card
文件夹,打开文件_cq_dialog/.content.xml
.此文件是组件对话框定义
Card
组件。 如果使用Sling继承,则可以使用的 Sling资源合并器 覆盖或扩展对话框的各个部分。 在此示例中,向对话框添加了一个新选项卡,用于从作者捕获其他数据以填充卡组件。属性,如
sling:orderBefore
允许开发人员选择插入新选项卡或表单字段的位置。 在本例中,Text
选项卡插入在asset
选项卡。 为了充分利用Sling资源合并器,了解 图像组件对话框. -
在
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
、图像和图像组件的子后代是例外。 -
在IDE中,切换到
ui.frontend
模块,导航到ui.frontend/src/app/components/card
: -
Inspect文件
card.component.ts
.该组件已被清除以映射到AEM
Card
使用标准的组件MapTo
函数。code language-js MapTo('wknd-spa-angular/components/card')(CardComponent, CardEditConfig);
查看三个
@Input
的类中的参数src
,alt
、和title
. 这些是AEM组件中映射到Angular组件的JSON值。 -
打开文件
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
组件需要更新模板策略。
-
将起始代码部署到AEM的本地实例(如果尚未部署):
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage
-
导航至SPA页面模板,网址为 http://localhost:4502/editor.html/conf/wknd-spa-angular/settings/wcm/templates/spa-page-template/structure.html.
-
更新布局容器的策略以添加新的
Card
组件作为允许的组件:保存对策略所做的更改,并观察
Card
组件作为允许的组件:
创作初始卡组件
接下来,创作 Card
组件使用AEM SPA编辑器。
-
导航到 http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html.
-
在
Edit
模式,添加Card
组件到Layout Container
: -
将图像从资产查找器拖放到
Card
组件: -
打开
Card
“组件”对话框,并注意添加了 文本 选项卡。 -
请在以下位置输入以下值 文本 选项卡:
信息卡路径 — 在SPA主页下选择页面。
CTA文本 — “了解更多”
卡片标题 — 留空
从链接的页面获取标题 — 选中复选框以指示true。
-
更新 资源元数据 制表符添加值 替换文本 和 题注.
更新对话框后,当前未显示其他更改。 要将新字段公开给Angular组件,我们需要更新的Sling模型
Card
组件。 -
打开新选项卡并导航到 CRXDE-Lite. Inspect下的内容节点
/content/wknd-spa-angular/us/en/home/jcr:content/root/responsivegrid
以查找Card
组件内容。观察该属性
cardPath
,ctaText
,titleFromPage
对话框将持久保留。
更新卡片Sling模型
要最终将组件对话框中的值显示给Angular组件,我们需要更新填充的JSON的Sling模型 Card
组件。 我们还有机会实施两种业务逻辑:
- 如果
titleFromPage
到 true,返回由指定的页面的标题cardPath
否则,返回值cardTitle
文本字段。 - 返回由指定的页的上次修改日期
cardPath
.
返回您选择的IDE并打开 core
模块。
-
打开文件
Card.java
在core/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
界面,就像我们在 自定义组件章节. -
将以下方法添加到接口:
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组件。
-
打开
CardImpl.java
. 这是的实施Card.java
界面。 为加速教程,已部分修剪此实施。 请注意,@Model
和@Exporter
注释,以确保能够通过Sling模型导出器将Sling模型序列化为JSON。CardImpl.java
也使用 Sling模型的委托模式 避免重写图像核心组件中的逻辑。 -
请注意以下行:
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()
. -
接下来,实施
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
变量,其他新方法使用该变量返回有关底层链接页面的数据。 -
查看已映射到JCR属性的全局变量,该属性保存了“作者”对话框。 此
@ValueMapValue
注释用于自动执行映射。code language-java @ValueMapValue private String cardPath; @ValueMapValue private String ctaText; @ValueMapValue private boolean titleFromPage; @ValueMapValue private String cardTitle;
这些变量用于实现的其他方法
Card.java
界面。 -
实施中定义的其他方法
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. -
打开终端窗口,将更新仅部署到
core
模块使用MavenautoInstallBundle
配置文件来自core
目录。code language-shell $ cd core/ $ mvn clean install -PautoInstallBundle
如果使用 AEM 6.x 添加
classic
个人资料。 -
在以下位置查看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模型已为 ctaLinkURL
, ctaText
, cardTitle
、和 cardLastModified
我们可以更新Angular组件以显示这些内容。
-
返回到IDE并打开
ui.frontend
模块。 (可选)从新终端窗口启动webpack开发服务器以实时查看更改:code language-shell $ cd ui.frontend $ npm install $ npm start
-
打开
card.component.ts
在ui.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;
-
添加用于检查行动号召是否准备就绪以及根据
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; } ... }
-
打开
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卡组件代码. -
使用Maven从项目的根目录部署对AEM的完整更改:
code language-shell $ cd aem-guides-wknd-spa $ mvn clean install -PautoInstallSinglePackage
-
导航到 http://localhost:4502/editor.html/content/wknd-spa-angular/us/en/home.html 要查看更新的组件,请执行以下操作:
-
您应该能够重新创作现有内容以创建类似于以下内容的页面:
恭喜! congratulations
恭喜,您已了解如何扩展AEM组件以及Sling模型和对话框如何与JSON模型一起使用。
您始终可以在上查看完成的代码 GitHub 或者切换到分支机构在本地签出代码 Angular/extend-component-solution
.