Create a custom CMS component in Hybris
CMS Components is what makes the WCMS module of SAP Hybris so powerful and so flexible.
In this article, I will show you how to create a custom cms component in Hybris.
1. Overview
A cms component consists of three elements interact with one another : Model, JSP and Controller.
- Model : identify the component with a uid, name, catalog version and also holds the inputs to be sent to the JSP.
- JSP : is the template of the component, describe the look and feel of it.
- Controller : is the mediator between the Model and the JSP, inputs are sent from the Model to the JSP with the help of it.
In SAP Hybris there are already many cms components come within the Accelerator hence for the most cases there is no need to create new components.
Example Out-of-the-Box components: CMSParagraphComponent, CMSImageComponent, BannerComponent, CMSLinkComponent…
2. Implementation
Let’s try to create a new component, in Hybris there is no Out-of-the-Box component allows to display an embed video, so let’s try it 🙂
We will use YouTube’s script to add embed videos to our pages :
<iframe
width="700"
height="400"
src="https://www.youtube.com/embed/xcJtL7QggTI?autoplay=0&controls=1">
</iframe>
This script needs five inputs, they are the inputs for our component :
- width : video frame width (700).
- height : video frame height (400).
- autoplay : play or not the video automatically (1 or 0).
- controls : display or not Player controls (1 or 0).
- videoId : the id of the video (xcJtL7QggTI).
2.1. Create the Model
Create a new itemType
with YoutubeVideoComponent
as a name and extends SimpleCMSComponent
.
<itemtype code="YoutubeVideoComponent"
extends="SimpleCMSComponent"
jaloclass="com.stackextend.training.jalo.components.YoutubeVideoComponent">
<attributes>
<attribute qualifier="width" type="java.lang.Integer">
<modifiers/>
<persistence type="property"/>
</attribute>
<attribute qualifier="height" type="java.lang.Integer">
<modifiers/>
<persistence type="property"/>
</attribute>
<attribute qualifier="videoId" type="java.lang.String">
<modifiers/>
<persistence type="property"/>
</attribute>
<attribute qualifier="autoPlay" type="java.lang.Boolean">
<modifiers/>
<persistence type="property"/>
</attribute>
<attribute qualifier="showControls" type="java.lang.Boolean">
<modifiers/>
<persistence type="property"/>
</attribute>
</attributes>
</itemtype>
2.2. Create the JSP
The JSP is where we will put YouTube’s script, the JSP file should have the same name as the Model youtubevideocomponent.jsp
.
<%-- web/webroot/WEB-INF/views/desktop/cms/youtubevideocomponent.jsp --%>
<%@ page trimDirectiveWhitespaces="true" %>
<iframe
width="${width}"
height="${height}"
src="https://www.youtube.com/embed/${videoId}?autoplay=${autoPlay}&controls=${showControls}">
</iframe>
2.3. Create the Controller
It’s a basic Spring MVC controller extends the AbstractCMSComponentController
and implements fillModel(...)
.
package com.stackextend.training.storefront.controllers.cms;
import ...;
@Scope("tenant")
@Controller("YoutubeVideoComponentController")
@RequestMapping("/view/YoutubeVideoComponentController")
public class YoutubeVideoComponentController
extends AbstractCMSComponentController<YoutubeVideoComponentModel>
{
@Override
protected void fillModel(HttpServletRequest request, Model model, YoutubeVideoComponentModel component) {
model.addAttribute("width", component.getWidth());
model.addAttribute("height", component.getHeight());
model.addAttribute("videoId", component.getVideoId());
model.addAttribute("autoPlay", BooleanUtils.toBoolean(component.getAutoPlay()) ? 1 : 0);
model.addAttribute("showControls", BooleanUtils.toBoolean(component.getShowControls()) ? 1 : 0);
}
}
Our new cms component is now ready to be used, let’s attach it to the home page of our website 😀
2.4. Use the Component
Create an instance of the component using Impex or directly from HMC, fill the inputs with the appropriate data.
Attach the component MyYoutubeVideoComponent
to a ContentSlot of the home page (Section3 for example).
If everything goes will this is how our CMS Component will look like in the home page.
3. Conclusion
This is a basic example on how to create a cms component, that could be extended to create more complex cms component.
Software Craftsmanship, Stackextend author and Full Stack developer with 6+ years of experience in Java/Kotlin, Java EE, Angular and Hybris…
I’m Passionate about Microservice architectures, Hexagonal architecture, Event Driven architecture, Event Sourcing and Domain Driven design (DDD)…
Huge fan of Clean Code school, SOLID, GRASP principles, Design Patterns, TDD and BDD.
Hi Mouad ,
How we can fetch category image in our Custom component (i.e fillModel method) at run time
Hi Itesh, Actually the CMS Controller is here to give you the flexibility to do whatever you need before the component is being displayed : In case you need to display one single category image only : You have to attach the CategoryModel to the CustomCMSComponentModel, and inside fillModel retrieve the category image like this : model.addAttribute("image", component.getCategory().getPicture()), then use <img src="${image.url}" /> in the jsp. However if your CMS Component should display all categories image : You have to use FlexibleSearchService to fetch all categories image with a FlexibleSearch, then fill a new attribute with the images, and inside… Read more »
how to attach the CategoryModel to the CustomCMSComponentModel
thank yououou very useful
Glad it helped 🙂
Hi Mouad,
How do you override CMS component jsp in an addon
Hi, this is a very interesting question in my opinion, I may write something later about it!
A quick brief answer would be :
1. Make Your [CMSComponentConroller] extends
AbstractCMSAddOnComponentController
instead ofAbstractCMSComponentController
.2. Customize and copy your component’s jsp from :
yacceleratorstorefront/web/webroot/WEB-INF/views/desktop/cms/[yourcomponent.jsp]
to :
yourAddon/web/webroot/WEB-INF/views/desktop/cms/[yourcomponent.jsp]
Thanks for the reply Mouad,
I see when you override the PageTemplate you can write an impex below and your store then use the addon pages. They is no other way to do same on CMS components without having to extends controllers?
;;SearchResultsEmptyPageTemplate;Search Results Empty Page Template;addon:/myAddon/pages/search/searchEmptyPage;ContentPage
Unfortunately this is only possible for
PageTemplates
where the view path is configured via HMC or Impex.While for
CMSComponents
the view path is calculated dynamically inside thegetView(final T component)
method ofAbstractCMSComponentController
andAbstractCMSAddOnComponentController
.Thanks Mouad will explore that approach
Good day Mouad,
I followed your approach mentioned above but when i run the system the yacceleratorstorefront cms is the one been used instead of the addon
Thank you for this tutorial Mouad. Following this approach, can we change or author the youtube link from smart edit.
I mean i want to create a video component but at the same time i should be able to change or author different youtube links via smart edit.
Hello Mouad! Let’s say that I’ve create my custom cms component. Also, I created a new ContentSlot, ContentSlotName and assigned my component to that slot using ContentSlotForPage. Now I display it using “<cms:pageSlot …". So far so good. It is presented both on the Staged and, after synchronization, on the Online catalog version. But I want to be able to edit this component in the WCMS cockpit. I found out that editing .vm template files is needed. Still, having added my own 'section' in the corresponding .vm template file, I see no changes. So, I want to see my ContentSlot… Read more »
Hello Nick,
You still need just one more step to achieve your goal, it is importing the updated velocity template
.vm
into yourPageTemplate
using thecms-content.impex
orcms-responsive-content.impex
.The full path to the impexes are :
…/traininginitialdata/import/coredata/contentCatalogs/catalogName/cms-content.impex
…/traininginitialdata/import/coredata/contentCatalogs/catalogName/cms-responsive-content.impex
So after updating the velocity template, navigate to the HAC and run an Update with project data of the traininginitialdata extension toggled to true, hence the
cms-content.impex
andcms-responsive-content.impex
will be imported whiten the process of the update.Then go to WCMS Cockpit -> Menu -> User settings -> Reset personalized settings
Good luck 🙂
Yep, it kinda helped. However, in my case, toggling the project data from “traininginitialdata” on is not enough. Guess, there also must be some additional project data selected as when I update project data for all the available extensions, it works fine.
Anyway, I will find it out by trial and error 🙂
Thank you so much for your quick reply. Keep doing the great job!
I’m glad it helped!
I think in your case you may need to toggle the project data for apparelstore and electronicstore extensions too.
Hi Mouad,
I’m trying to create a sidebar on a hybris page.
my question is:
how can I make sure that the sidebar can be seen in all the pages, in the same way as the navbar.
could you indicate a safe way to solve this problem?
thank you
Raffaele
Hi,
Well, you have to attach the sidebar to every template of your website instead of attaching it directly to a page, in this case the sidebar will be seen in all the pages.
Hi Mouad, thanks for the reply.
I should put the sidebar on the homepage of my site and display it on every page, just like the navigation bar.
Would there be a guide to do this?
Thank you
Raffaele
I actually you have to put your sidebar on the template, have a look a this post to understand the structure of the CMS : https://www.stackextend.com/hybris/everything-about-wcms-in-hybris/
Hi Mouad
Thanks so much
I will try to follow your guide and your advice.
Bye
Thank you for this tutorial Mouad. Following this approach, can we change or author the youtube link from smart edit.
I mean i want to create a video component but at the same time i should be able to change or author different youtube links via smart edit.
Well, what is certain is that you can do that from HMC, Backoffice and CMSCockpit, I’m not quite familiar with Smart edit however I think it is not an exception.
Thank for the reply. i did try out in smart edit, i was able to author the links with few changes.
Well in our project, client prefers smart edit rather than CMSCockpit or backoffice .
Good, thanks for your feedback!
Hi Mouad,
I want to show the attributes in certain order like first height , then videoId, then width and so on. How to achieve this ordering while opening the component? Mentioning in this order in items.xml doesn’t work.
UOOW Great man!! Helped me a lot!
Hi Mouad,
1. Is it by convention the Name of controller should be same as Model with Controller prefix.
2. Is it possible to skip the Controller creation .
Regards,
Prajwal
HI Mouad,
Is it cumpulsory to create a controller in order to add new component.
Are their any other way out without adding the controller way.
Basically the controller is not compulsory for new custom component, and what really happens when you create a new component without its Controller
the component will be based on a default controller (com.wonder.storefront.controllers.cms.DefaultCMSComponentController) who is going to fill all components attributes on model
and you can get access to them from jsp by ${component.customAttribute}
I hope this is unswerving your question.
Thanks for the reply.
Hi Mouad,
Is there a way to show the component in a specific location in a page? In my solution, i have a Page JSP (Not a component) and i wish to replace an image with a CMS Image Component between 2 paragraphs. Look a bit different than your example.
Thanks!