When a CMS Component contains other components, it is a requirement that any changes of the childrens, the synchronization of the parent trigger. It is difficult to get this right, as there are limitations on the identification of changes on the WCMS. This is what has worked for me.

Introduction

The requirement is to show tabs in the pages accessible by the registered users. The order and other properties like the title may be changed by the customer on the WCMS. Currently each page has only one group of tabs but this may change in the future.

Data model

hybris/bin/custom/customcms/resources/customcms-items.xml
<relation code="TabGroup2AbstractTabCMSComponent" generate="true" localized="false" autocreate="true"> <deployment table="tabgroup2tab" typecode="30099" /> <sourceElement qualifier="tabGroups" type="TabGroupCMSComponent" cardinality="many"/> <targetElement qualifier="tabs" type="AbstractTabCMSComponent" cardinality="many" collectiontype="list" ordered="true"/> </relation> <itemtype code="TabGroupCMSComponent" autocreate="true" generate="true" extends="AbstractCMSComponentContainer" jaloclass="customcms.jalo.components.TabGroupCMSComponent"> <description>It holds a group of tabs. The CMS cockpit sees the changes on the childs because it inherites from AbstractCMSComponent </description> </itemtype> <itemtype code="AbstractTabCMSComponent" generate="true" extends="AbstractCMSComponent" autocreate="true" abstract="false" jaloclass="customcms.cms.jalo.components.AbstractTabCMSComponent"> <description>Represents a tab component hold by a tab group.</description> <attributes> <attribute qualifier="tag" type="java.lang.String"> <persistence type="property"/> <description>A tag used for identifying the component within its parent component.</description> </attribute> <attribute qualifier="title" type="localized:java.lang.String"> <persistence type="property"/> </attribute> <attribute qualifier="tabbodyCaption" type="localized:java.lang.String"> <persistence type="property"/> </attribute> <attribute qualifier="tabbodyInfo" type="localized:java.lang.String"> <persistence type="property"/> </attribute> </attributes> </itemtype>

The important points to consider are:

  • The parent component inherits from AbstractCMSComponentContainer.
  • The child component isn't abstract
  • The child component inherits from AbstractCMSComponent.

Here is the definition of the childs which doesn't have anything special:

hybris/bin/custom/customcms/resources/customcms-items.xml
<itemtype code="ReportsCMSComponent" generate="true" extends="AbstractTabCMSComponent" autocreate="true" jaloclass="customcms.jalo.components.ReportsCMSComponent"> <description>Component for requesting reports for customer</description> <attributes/> </itemtype> <itemtype code="EnableOrdersCMSComponent" generate="true" extends="AbstractTabCMSComponent" autocreate="true" jaloclass="customcms.jalo.components.EnableOrdersCMSComponent"> <description> Orders - 'Enable orders' Component</description> <attributes/> </itemtype> <itemtype code="OrderHistoryCMSComponent" generate="true" extends="AbstractTabCMSComponent" autocreate="true" jaloclass="customcms.jalo.components.OrderHistoryCMSComponent"> <description> Orders - 'All orders' Component</description> <attributes/> </itemtype>

Synchronization Service

In the custom CMS cockpit extension  the new attributes must be configured.

hybris/bin/custom/customcmscockpit/resources/customcmscockpit/customcmscockpit-spring-services.xml
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-autowire="byName"> <alias alias="synchronizationService" name="customSynchronizationService" /> <bean id="customSynchronizationService" class="de.hybris.platform.cmscockpit.sync.CMSSynchronizationService" scope="tenant" autowire="byName"> <property name="relatedReferencesTypesMap"> <map> <entry key="AbstractPage"> <list> <value>AbstractPage.restrictions</value> <value>AbstractPage.contentSlots</value> <value>ContentSlotForPage.contentSlot</value> <value>ContentSlot.cmsComponents</value> <value>AbstractCMSComponentContainer.simpleCMSComponents</value> <value>AbstractCMSComponentContainer.currentCMSComponents</value> <value>RotatingImagesComponent.banners</value> <value>AbstractCMSComponent.restrictions</value> <value>abstractMediaContainerComponent.media</value> <value>TabGroupCMSComponent.tabs</value> </list> </entry> <entry key="AbstractCMSComponent"> <list> <value>AbstractCMSComponentContainer.simpleCMSComponents</value> <value>AbstractCMSComponentContainer.currentCMSComponents</value> <value>RotatingImagesComponent.banners</value> <value>CMSProductCarouselComponent.carouselElements</value> <value>ContentSlot.cmsComponents</value> <value>AbstractCMSComponentContainer.simpleCMSComponents</value> <value>AbstractCMSComponentContainer.currentCMSComponents</value> <value>RotatingImagesComponent.banners</value> (...) <value>MediaContainer.medias</value> <value>NavigationBarCollectionComponent.components</value> <value>NavigationBarComponent.navigationNode</value> <value>NavigationBarComponent.link</value> <value>TabGroupCMSComponent.tabs</value> </list> </entry> <entry key="CMSNavigationNode"> <list> <value>CMSNavigationNode.children</value> <value>CMSNavigationNode.entries</value> <value>CMSNavigationNode.links</value> <value>CMSNavigationEntry.item</value> <value>CMSLinkComponent</value> </list> </entry> <entry key="ContentSlot"> <list> <value>ContentSlot.cmsComponents</value> <value>abstractMediaContainerComponent.media</value> <value>NavigationBarCollectionComponent.components</value> <value>NavigationBarComponent.navigationNode</value> <value>NavigationBarComponent.link</value> </list> </entry> <entry key="MediaContainer"> <list> <value>MediaContainer.medias</value> </list> </entry> <entry key="TabGroupCMSComponent"> <list> <value>TabGroupCMSComponent.tabs</value> </list> </entry> <entry key="AbstractTabCMSComponent"> <list> <value>AbstractTabCMSComponent.title</value> <value>AbstractTabCMSComponent.tabGroups</value> </list> </entry> </map> </property> <property name="modelService" ref="modelService"/> <property name="cockpitTypeService" ref="cockpitTypeService"/> <property name="searchRestrictionsDisabled" value="true"/> </bean> (...) </beans>

Probably is some of the configuration duplicated but it works.

Localization (optional)

The new components must be localized as any other Hybris type. 

hybris/bin/custom/customcms/resources/localization/customcms-locales_en.properties
### Localization for type TabGroupCMSComponent type.tabgroupcmscomponent.name=Tab group component type.tabgroupcmscomponent.tabs.name=Tabs ### Localization for type AbstractTabCMSComponent type.abstracttabcmscomponent.name=Abstract Tab component type.abstracttabcmscomponent.tabgroups.name=Tab groups type.abstracttabcmscomponent.tabbodycaption.name=Section caption type.abstracttabcmscomponent.tabbodyinfo.name=Section text type.abstracttabcmscomponent.tag.name=Tag type.abstracttabcmscomponent.title.name=Title.

Jalo Classes

Two methods must be implemented:

package customcms.jalo.components;

import de.hybris.platform.cms2.jalo.contents.components.SimpleCMSComponent;
import de.hybris.platform.jalo.SessionContext;

import java.util.List;


public class TabGroupCMSComponent extends GeneratedTabGroupCMSComponent
{
    @Override
    public Boolean isContainer(SessionContext sessionContext) {
        return Boolean.TRUE;
    }


    @Override
    public List<SimpleCMSComponent> getCurrentCMSComponents(SessionContext sessionContext) {
        return this.getSimpleCMSComponents(sessionContext);
    }
}

package customcms.jalo.components;

import de.hybris.platform.jalo.SessionContext;

public class AbstractTabCMSComponent extends GeneratedAbstractTabCMSComponent
{

    @Override
    public Boolean isContainer(SessionContext sessionContext) {
        return Boolean.TRUE;
    }
}

CMS Cockpit Configuration

The changes on the child are identified when the tag property is used in the cockpit configuration of the parent is used:

hybris/bin/customcmscockpit/resources/customcmscockpit-config/cmsmanagergroup/contentEditor_TabGroupCMSComponent.xml
<?xml version="1.0" encoding="UTF-8"?>
<content-editor hideEmpty="false" hideReadOnly="false" groupCollections="false">
  <template>
    <![CDATA[
        <div class="contentEditorWrapper">
            <div class="contentEditorHeader">
                <b>$label</b>
            </div>
            <div class="contentEditorLine">
                <cockpit code="property" value="TabGroupCMSComponent.visible"/>
            </div>
            <div class="contentEditorLine">
                <cockpit code="property" value="TabGroupCMSComponent.tabs"/>
            </div>
        </div>
    ]]>
  </template>
</content-editor>

The Cockpit configuration of the childs doesn't contain anything special:

hybris/bin/customcmscockpit/resources/customcmscockpit-config/cmsmanagergroup/contentEditor_AbstractTabCMSComponent.xml
<?xml version="1.0" encoding="UTF-8"?>
<content-editor hideEmpty="true" hideReadOnly="true" groupCollections="true">
  <template>
    <![CDATA[
        <div class="contentEditorWrapper">
            <div class="contentEditorHeader">
                <b>$label</b>
            </div>
            <div class="contentEditorLine">
                <cockpit code="property" value="AbstractTabCMSComponent.tag"/>
            </div>
            <div class="contentEditorLine">
                <cockpit code="property" value="AbstractTabCMSComponent.title"/>
            </div>
            <div class="contentEditorLine">
                <cockpit code="property" value="AbstractTabCMSComponent.tabbodyCaption"/>
            </div>
            <div class="contentEditorLine">
                <cockpit code="property" value="AbstractTabCMSComponent.tabbodyInfo"/>
            </div>
        </div>
    ]]>
  </template>
</content-editor>

hybris/bin/customcmscockpit/resources/customcmscockpit-config/cmsmanagergroup/editorArea_AbstractTabCMSComponent.xml
<?xml version="1.0" encoding="UTF-8"?>
<editor>

    <group qualifier="general" visible="true" initially-opened="true">
        <label lang="de">Stammdaten</label>
        <label lang="en">General</label>
        <property qualifier="CMSItem.name"/>
        <property qualifier="CMSItem.catalogVersion" editor="shortListEditor"/>
        <property qualifier="AbstractTabCMSComponent.title"/>
        <property qualifier="AbstractTabCMSComponent.tabbodyCaption"/>
        <property qualifier="AbstractTabCMSComponent.tabbodyInfo"/>
    </group>

    <group qualifier="visibility" visible="true" initially-opened="false">
        <label lang="de">Context Visibility</label>
        <label lang="en">Context Visibility</label>
        <property qualifier="AbstractCMSComponent.restrictions">
            <parameter>
                <name>allowCreate</name>
                <value>true</value>
            </parameter>
        </property>
        <property qualifier="AbstractCMSComponent.onlyOneRestrictionMustApply"/>
    </group>

	<group qualifier="admin" visible="false" initially-opened="false">
		<label key="config.general.administration" />
		<property qualifier="Item.pk" />
		<property qualifier="Item.creationTime" />
		<property qualifier="Item.modifiedtime" />
	</group>

    <custom-group
            class="de.hybris.platform.cockpit.services.config.impl.UnassignedEditorSectionConfiguration"
            qualifier="unassigned"
            initially-opened="false"
            visible="false">
        <label lang="de">Andere</label>
        <label lang="en">Other</label>
    </custom-group>

</editor>

Views

The JSP file must include CMS tags which render the childs as any other CMS component container:

hybris/bin/custom/customstorefront/web/webroot/WEB-INF/views/cms/tabgroupcmscomponent.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="links" uri="http://www.springframework.org/tags/form" %>

(...)

<c:forEach var="tabcomponent" items="${tabcomponents}" begin="0"> <cms:component component="${tabcomponent}"/> </c:forEach> (...)

 

Based on Hybris 5.5.1

Add comment


Security code
Refresh