Defining storefront assets for a Commerce Composer widget
Before you begin
- Ensure that you are familiar with the components that make up the storefront assets for a widget. For more information, see Widget architecture.
- Ensure that you complete the task to generate the source code for your Commerce Composer widget.
Procedure
- In the Enterprise Explorer view, create a directory to
contain the code packages for custom widgets.Within this directory, create the code package that is to contain all of the assets for your custom widget that are not shared among multiple widgets. If your site has multiple custom widgets, ensure that the assets for each custom widget are in separate code packages.The code packages that define the default site-level widgets are in the following directory:
- WCDE_installdir\workspace\Stores\WebContent\widgetdir
If you are creating a custom site-level widget, create the following directory, if the directory does not exist:- WCDE_installdir\workspace\Stores\WebContent\Widgets-vendor
If you are creating a custom store-level widget, create a store-specific directory that contains the Widgets-vendor directory, if the directory does not exist:- WCDE_installdir\workspace\Stores\WebContent\store\Widgets-vendor
If your custom widget has assets that are common across multiple widgets, but the assets are not already included in the default Widgets\Common directory, include these assets in a Common directory in the Widgets-vendor directory. If this Common directory, does not exist, you must create the directory.
- Copy the generated source code files for your widget storefront
assets from the target folder into the default WebSphere Commerce
Developer workspace file structure.
- Go to the project where the JET Transformation generated
the source code files in the previous task. Copy the following file
structure and files that are within the target folder:
- target_folder\Stores\WebContent\Widgets-vendor\Common
- target_folder\Stores\WebContent\Widgets-vendor\images
- target_folder\Stores\WebContent\Widgets-vendor\Properties
- target_folder\Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\javascript
- target_folder\Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier.jsp
- target_folder\Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier_Data.jspf
- target_folder\Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier_UI.jspf
- target_folder\Stores\WebContent\Widgets-vendor\Properties\MyWidgetText_en_US.properties
- target_folder\Stores\WebContent\Widgets-vendor\Properties\MyWidgetText.properties
- vendor
- The value for the
vendor
parameter within the pattern input XML file. - identifier
- The value for the
identifier
parameter within the pattern input XML file. - target_folder
- The folder or project that you specified as the value for the
targetFolder
parameter in the pattern input XML file. If you did not specify a value for thetargetFolder
parameter, the target_folder is the folder or project where the pattern input XML file is located.
- Merge the copied files and file structure into the default
WebSphere Commerce Developer workspace file structure. Do not overwrite
any files or folders.If you are creating a store level widget, add the Widgets-vendor directory and the contents of the directory into your Stores\WebContent\store directory. Where store is the name of your store directory.
- Go to the project where the JET Transformation generated
the source code files in the previous task. Copy the following file
structure and files that are within the target folder:
- Complete the entry point top-level JSP file for your custom
widget.This JSP file identifies the environment setup file, the data provider, and the UI provider to import for rendering the widget. If your widget requires multiple UI providers, the top-level JSP file includes the code that specifies the conditions when each UI provider is used to render the widget.
The filepath to this top-level JSP file must be registered with the widget identifier in the Commerce Composer framework. The top-level JSP file is imported into Commerce Composer layouts when a widget is assigned to a layout. When a layout that includes the widget is assigned to a store page, the top-level JSP file is used to call the components to provide the widget function.
- Go to the following merged directory:
- For site-level widgets - Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- For store-level widgets - Stores\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- Open the identifier.jsp file
for editing.By default, the generated source code file includes the following code to help you define the top-level JSP file for your widget:
<%-- The following code is created as an example. Modify the generated code and add any additional required code. --%> <%-- BEGIN identifier.jsp --%> 1 <%@include file="/Widgets/Common/EnvironmentSetup.jspf"%> 2 <fmt:setBundle basename="/Widgets-vendor/Properties/mywidgettext" var="mywidgettext" /> <c:set var="widgetPreviewText" value="${mywidgettext}"/> <c:set var="emptyWidget" value="false"/> 3 <%@include file="identifier_Data.jspf"%> 4 <c:if test="${env_inPreview && !env_storePreviewLink}"> <jsp:useBean id="previewWidgetProperties" class="java.util.LinkedHashMap" scope="page" /> <c:set target="${previewWidgetProperties}" property="name" value="${param.name}" /> <c:set target="${previewWidgetProperties}" property="name" value="${param.name}" /> </c:if> 5 <%@ include file="/Widgets/Common/StorePreviewShowInfo_Start.jspf" %> 6 <%@ include file="identifier_UI.jspf"%> 5 <%@ include file="/Widgets/Common/StorePreviewShowInfo_End.jspf" %> <%-- END identifier.jsp --%>
- 1 The environment setup file. This configuration file is used at run time. This file retrieves and prepares the JSP page path, file path, and resource bundle for the widget. This file is called by many JSP files in a store and is shared by multiple widgets. By default, the /Widgets/Common/EnvironmentSetup.jspf file is specified.
- 2 The property resource bundle for your widget. A properties file is a resource bundle that contains the translatable text for display in the widget. By default, the generated \Widgets-vendor\Properties\MyWidgetText.properties file is specified.
- 3 Identifies the data provider to use for retrieving content for use in the widget. The generated identifier_Data.jspf data provider is set by default.
- 4 The conditional statement determine whether the widget is being viewed in store preview. If the widget is being viewed in store preview, this code adds the logic to ensure that the widget properties are used to render the widget during store preview. The name field identifies the configurable property.
- 5 The StorePreviewShowInfo_Start.jspf and StorePreviewShowInfo_End.jspf files add support for showing information about the widget when the widget is being viewed in store preview. The include statements for these files must enclose the include statement and logic that define the display information for the widget.
- 6 Identifies the UI provider to use for rendering the widget on a store page. The generated identifier_UI.jspf UI provider is set by default.
Modify the generated top-level JSP file. Change any of the default settings or specify more properties to meet the requirements for your custom widget.
- Optional: If your widget requires multiple
UI providers, include conditional statements to define the conditions
when each UI provider is to be used.You can define configurable properties to allow Management Center users to select the rendering style. Use the values for the configurable properties as the conditions within the conditional statements. For example, the following code sets the conditions for when each UI provider is to be used to render the Catalog Entry Recommendation widget.
The CatalogEntryRecommendation.jsp top-level JSP file specifies that the catalog entry recommendation widget can be rendered differently depending on which UI provider is used to render the widget.1 <c:if test="${!empty catentryIdList}"> <c:choose> 2 <c:when test="${param.widgetOrientation eq 'vertical'}"> <%@include file="CatalogEntryRecommendation_Vertical_UI.jspf"%> </c:when> 3 <c:otherwise> <%@include file="CatalogEntryRecommendation_Horizontal_UI.jspf"%> </c:otherwise> </c:choose> </c:if>
- 1 Conditional statement to check that a custom view is not set for the widget and that there are recommendations to retrieve for display within the widget. If the condition is met, then the top-level JSP file uses the conditional statements to check to select the appropriate UI provider to render the widget.
- 2 Conditional statement to test
whether the widget orientation parameter is set to
'vertical'
. If the value is set to'vertical'
, the CatalogEntryRecommendation_Vertical_UI.jspf is used to render the widget. Business users can set the value for the widget orientation parameter in Management Center. - 3 If the widget orientation parameter
is not set to
'vertical'
, the CatalogEntryRecommendation_Horizontal_UI.jspf is used to render the widget.
- Optional: If you define any properties for
your widget, define a
previewWidgetProperties
map to display the properties in the Widget Information window for your widget in store preview.Use the following format to define thepreviewWidgetProperties
map:
Where<c:if test="${env_inPreview && !env_storePreviewLink}"> <jsp:useBean id="previewWidgetProperties" class="java.util.LinkedHashMap" scope="page" /> <c:set target="${previewWidgetProperties}" property="name" value="${param.name}" /> <c:set target="${previewWidgetProperties}" property="name" value="${param.name}" /> </c:if>
name
- The name of the property for your custom widget. For example,
widgetOrientation
. This property name corresponds to a key in the properties resource bundle. If the key is not found, the provided name displays in the Widget Information window. value
- The value for each property can correspond to a key in the properties
resource bundle with the format
name_value
. If the key is not found in the properties resource bundle, the provided value displays in the Widget Information window.
- Optional: If your custom widget must use
data that is generated by a different widget, you can use a Dojo event
to retrieve the information for your custom widget.If a widget publishes a Dojo event that contains any required data for your widget, you can have your custom widget subscribe to the Dojo event to retrieve the data. For more information, see Publishing and retrieving information with Dojo events for widgets.
- Optional: If your custom widget must generate
data for other widgets to use, you can use a Dojo event to publish
the data.The other widgets can then subscribe to the published Dojo event. For more information, see Publishing and retrieving information with Dojo events for widgets.
- Save the file.As an example of a top-level JSP file, the following code defines the top-level JSP file, Heading.jsp, for the Heading widget:
<!-- BEGIN Heading.jsp --> <%@ include file="/Widgets/Common/EnvironmentSetup.jspf" %> <c:set var="emptyWidget" value="false"/> <%@include file="Heading_Data.jspf"%> <%@ include file="/Widgets/Common/StorePreviewShowInfo_Start.jspf" %> <%@include file="Heading_UI.jspf"%> <%@ include file="/Widgets/Common/StorePreviewShowInfo_End.jspf" %> <wcpgl:pageLayoutWidgetCache/> <!-- END Heading.jsp -->
Note: The preceding top-level JSP file for the Heading widget, includes the code<wcpgl:pageLayoutWidgetCache/>
, This tag is used for caching the widget. For more information about widget caching, see Commerce Composer widget caching and invalidation.For an example of a top-level JSP file for a widget that uses marketing activities, see the Content Recommendation widget top-level JSP file- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation.jsp
- Go to the following merged directory:
- Define the data provider JSP fragment for your custom widget.
The top-level JSP file calls the data provider file to retrieve the data that is needed to render the widget. A widget can have only one data provider, which is modeled as an independent JSP page.
- Go to the following merged directory:
- For site-level widget - Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- For store-level widgets - Stores\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- Open the identifier_Data.jspf file
for editing.
By default, the generated source code file is empty. Add the code to define the data that is to be retrieved for your custom widget. If your custom widget uses the same data as an existing widget, use the data provider file for the existing widget to help you define the file for your custom widget.
To locate the data provider file for an existing widget go to the Stores\WebContent\widgetdir directory. Expand the directory and the code package for an existing widget. Open the identifier_Data.jspf for the existing widget.
If you are converting an existing store JSP file to be a widget, use the contents of your JSP file to help you define the data provider information for the widget. Review your JSP and identify the code that is related to data. Modify and include this data-related code into the data provider file for your widget. If the JSP file that you are converting has include or import statements, move the referenced JSP files into the Stores\WebContent\Widgets-vendor\Common directory. Update the references in your data provider file to reference the new filepaths.
- Save the file.As an example of a data provider JSP fragment, the following code defines the data provider file, Heading_Data.jspf, for the Heading widget:
<%-- BEGIN Heading_Data.jsp --%> <%-- Try to get product description --%> <c:set var="productId" value="${param.productId}" /> <c:if test="${empty productId}"> <c:set var="productId" value="${WCParam.productId}" /> </c:if> <c:choose> <c:when test="${!empty productId}"> <%-- Try to get it from our internal hashMap --%> <c:set var="key1" value="${productId}+getCatalogEntryViewAllByID"/> <c:set var="catalogEntryDetails" value="${cachedCatalogEntryDetailsMap[key1]}"/> <c:if test="${empty catalogEntryDetails}"> <wcf:rest var="catalogNavigationView" url="${searchHostNamePath}${searchContextPath}/store/${WCParam.storeId}/productview/byId/${productId}" > <wcf:param name="langId" value="${langId}"/> <wcf:param name="currency" value="${env_currencyCode}"/> <wcf:param name="responseFormat" value="json"/> <wcf:param name="catalogId" value="${WCParam.catalogId}"/> </wcf:rest> <c:set var="catalogEntryDetails" value="${catalogNavigationView.catalogEntryView[0]}"/> </c:if> <c:if test="${!empty catalogEntryDetails}"> <c:set var="productName" value="${catalogEntryDetails.name}" /> <c:set var="catalogEntryID" value="${catalogEntryDetails.uniqueID}" /> </c:if> </c:when> <c:otherwise> <%-- Try to get category name --%> <c:set var="categoryId" value="${param.categoryId}" /> <c:if test="${empty categoryId}"> <c:set var="categoryId" value="${WCParam.categoryId}" /> </c:if> <c:if test="${!empty categoryId}"> <wcf:rest var="catGroupDetailsView" url="${searchHostNamePath}${searchContextPath}/store/${WCParam.storeId}/categoryview/byId/${categoryId}" > <wcf:param name="langId" value="${langId}"/> <wcf:param name="currency" value="${env_currencyCode}"/> <wcf:param name="responseFormat" value="json"/> <wcf:param name="catalogId" value="${WCParam.catalogId}"/> </wcf:rest> </c:if> <c:if test="${!empty catGroupDetailsView}"> <c:set var="categoryName" value="${catGroupDetailsView.catalogGroupView[0].name}"/> </c:if> </c:otherwise> </c:choose> <c:if test="${empty productId && empty categoryId}"> <c:set var="emptyWidget" value="true" /> </c:if> <c:set var="widgetSuffix" value="" /> <c:if test="${(!empty param.pgl_widgetSlotId) && (!empty param.pgl_widgetDefId) && (!empty param.pgl_widgetId)}"> <c:set var="widgetSuffix" value="_${param.pgl_widgetSlotId}_${param.pgl_widgetDefId}_${param.pgl_widgetId}" /> </c:if> <%-- END Heading_Data.jsp --%>
For an example of a data provider file for a widget that uses marketing activities, see the Content Recommendation widget data provider JSP fragment:- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Data.jspf
- Go to the following merged directory:
- Define the UI provider JSP fragment for your custom widget.
Each way that your custom widget can be rendered must be defined in a UI provider file. For example, if your custom widget can be rendered with both a horizontal and vertical orientation, you must define two UI provider files. Ensure that logic that defines the UI provider is included within the top-level JSP file.
- Go to the following merged directory:
- For site-level widgets - Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- For store-level widgets - Stores\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
- Open the identifier_UI.jspf file
for editing.By default, the generated source code file includes the following code to help you define the UI provider file for your widget:
<%-- Add your UI code here, see example below --%> 1 <div id="widgetExample" > <ul style="list-style: none; font-size: 24px"> <li>${param.name}</li> </ul> </div>
- 1 Example to demonstrate how to structure your UI provider JSP fragment.
- Modify the generated UI provider JSP fragment.
Identify the different divisions,
<div/>
, that must be defined to render your widget. Add code to define how each division can be rendered. Ensure that you include the rendering effects as JSP import parameters in your code. By including the effects as parameters, Management Center users can specify which rendering effects are to be used to render the widget on the storefront.If you are converting an existing store JSP file to be a widget, use the contents of your JSP file to define the UI provider information for the widget. Review your JSP file and identify the code that is related to rendering the JSP file. Modify and include the code that is related to rendering the JSP file within the UI provider file for your widget. If the JSP file that you are converting has include statements, move the referenced JSP files into the Stores\WebContent\Widgets-vendor\Common directory. Update the references in your data provider file to reference the new filepaths.
- Save the file.As an example of a UI provider JSP fragment, the following code defines the Heading_UI.jspf UI provider file for the Heading widget:
<%-- BEGIN Heading_UI.jsp --%> <div id="PageHeading<c:out value="${widgetSuffix}"/>" > <h1> <c:choose> <c:when test="${!empty categoryName}">${categoryName}</c:when> <c:when test="${!empty productName}">${productName}</c:when> </c:choose> </h1> </div> <%-- END Heading_UI.jsp --%>
For an example of a UI provider file for a widget that uses marketing activities, see the Content Recommendation widget UI provider JSP fragments. The Content Recommendation widget uses four UI provider JSP fragments to define all of the ways that the widget can be rendered.- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_UI.jspf
- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Email_UI.jspf
- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_URLLink_UI.jspf
- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Vertical_UI.jspf
- Go to the following merged directory:
- Define the translatable text that is to display in the
storefront for your custom widget.
- Go to the Stores\WebContent\Widgets-vendor\Properties directory.
- Open the generated MyWidgetText.properties for
editing. By default, the file includes the following property:
WidgetTypeDisplayText_identifier=displayName
- Add the translatable text for your widget into the file.
- Save your file.
- Repeat the preceding steps to edit the MyWidgetText_en_US.properties file to add translatable text for the United States English language.
- Optional: Add the language sensitive text for your widget in the other languages that your store supports. Create the properties files for your additional languages with the naming convention MyWidgetText_language.properties
- Create or move the CSS files for your widget.If your widget uses an existing CSS file, ensure that the file is in the appropriate directory for your store. For more information about the file structure of CSS files for Commerce Composer widgets, see Responsive Aurora starter store file structure.
If you must create a CSS file for your widget, consider defining the CSS to follow responsive web design practices. For more information about defining CSS to make a widget responsive, see Creating responsive widgets.
- Optional: If an image is required by your custom widget for display in the storefront, include the image within the Stores\WebContent\Widgets-vendor\images directory.
- Optional: Create any JavaScript functions that
are required for your custom widget.For example, adding support to add products to the shopping cart. If your widget does need JavaScript functions, you can create a new file to include all of the required JavaScript. Create your JavaScript file within the following directory:
- For site-level widgets - Stores\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\javascript
- For store-level widgets - Stores\WebContent\store\Widgets-vendor\om.vendor.commerce.store.widgets.identifier\javascript
- For site-level widgets - Stores\WebContent\Widgets-vendor\Common
- For store-level widgets - Stores\WebContent\store\Widgets-vendor\Common
To retrieve and use JavaScript for your widget, ensure that the widget definition XML for your widget references the JavaScript file.
For an example of a JavaScript asset for a widget, see the catalog entry recommendation widget JavaScript file.- Stores\WebContent\widgetdir\com.ibm.commerce.store.widgets.CatalogEntryRecommendation\javascript\CatalogEntryRecommendation.js
- Optional: If your custom widget uses a JSP
file, fragment, or other asset, move the asset into the common directory.
Ensure that your widget references the new filepath.
- For site-level widgets - Stores\WebContent\Widgets-vendor\Common
- For store-level widgets - Stores\WebContent\store\Widgets-vendor\Common
- Optional: If you are converting an existing
store JSP file to be a widget, edit the existing store JSP to remove
the code that you converted to a widget. Update the JSP file to call
the Commerce Composer tool to provide content for the store page by
including your custom widget in the page with the following code:
<c:import url= "${path to the widget top-level JSP file}"/>