HCL Commerce Developer

Defining storefront assets for a Commerce Composer widget

Create the JSP files, user interface provider files, and data provider files for your Commerce Composer widget. These storefront assets define the appearance and content of your widget.

Before you begin

Procedure

Part A: Move the generated source code files for the storefront assets of your widget into a code package within the default HCL Commerce Developer workspace file structure.
  1. 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:
    • workspace_dir\crs-web\WebContent\widgetdir
    The JSP files and JSP fragments that are shared between multiple widgets are stored in the Common directory within the widgetdir directory.
    If you are creating a custom site-level widget, create the following directory, if the directory does not exist:
    • workspace_dir\crs-web\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:
    • workspace_dir\crs-web\WebContent\store\Widgets-vendor
    Where store is the name of your store directory, for example aurora.

    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.

  2. Copy the generated source code files for your widget storefront assets from the target folder into the default HCL Commerce Developer workspace file structure.
    1. 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\crs-web\WebContent\Widgets-vendor\Common
      • target_folder\crs-web\WebContent\Widgets-vendor\images
      • target_folder\crs-web\WebContent\Widgets-vendor\Properties
      • target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\javascript
      • target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier.jsp
      • target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier_Data.jspf
      • target_folder\crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\identifier_UI.jspf
      • target_folder\crs-web\WebContent\Widgets-vendor\Properties\MyWidgetText_en_US.properties
      • target_folder\crs-web\WebContent\Widgets-vendor\Properties\MyWidgetText.properties
      Where
      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 the targetFolder parameter, the target_folder is the folder or project where the pattern input XML file is located.
    2. Merge the copied files and file structure into the default HCL 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 crs-web\WebContent\store directory. Where store is the name of your store directory.
Part B: Modify the generated source code files to complete the definition of the storefront assets for your custom widget.
  1. 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 file path 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.

    1. Go to the following merged directory:
      • For site-level widgets - crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
      • For store-level widgets - crs-web\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
    2. 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.

    3. 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.
      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>
      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 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.
      If no list of catalog entries is specified, the retrieved recommendations are rendered with the CatalogEntryRecommendation_Horizontal_UI.jspf UI provider. If a list of catalog entries are specified to display in the widget, the recommendations can be rendered with the CatalogEntryRecommendation_Vertical_UI.jspf or the CatalogEntryRecommendation_Horizontal_UI.jspf UI provider.
    4. 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 the previewWidgetProperties map:
      <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>
      Where
      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.
      Ensure that you include the corresponding properties within the properties resource bundle when you are adding Management Center support for your widget.
    5. Optional: If your custom widget must use data that is generated by a different widget, you can use a wcTopic event to retrieve the information for your custom widget.
      If a widget publishes a wcTopic event that contains any required data for your widget, you can have your custom widget subscribe to the wcTopic event to retrieve the data. For more information, see Publishing and retrieving information with wcTopic events for widgets.
    6. Optional: If your custom widget must generate data for other widgets to use, you can use a wcTopic event to publish the data.
      The other widgets can then subscribe to the published wcTopic event. For more information, see Publishing and retrieving information with wcTopic events for widgets.
    7. 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
      • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation.jsp
  2. 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.
    1. Go to the following merged directory:
      • For site-level widget - crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
      • For store-level widgets - crs-web\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
    2. 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 crs-web\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 crs-web\WebContent\Widgets-vendor\Common directory. Update the references in your data provider file to reference the new file paths.

    3. 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:
      • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Data.jspf
  3. 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.
    1. Go to the following merged directory:
      • For site-level widgets - crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
      • For store-level widgets - crs-web\WebContent\store\Widgets-vendor\com.vendor.commerce.store.widgets.identifier
    2. 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.
    3. 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 crs-web\WebContent\Widgets-vendor\Common directory. Update the references in your data provider file to reference the new file paths.

    4. 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.
      • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_UI.jspf
      • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Email_UI.jspf
      • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_URLLink_UI.jspf
      • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.ContentRecommendation\ContentRecommendation_Vertical_UI.jspf
  4. Define the translatable text that is to display in the storefront for your custom widget.
    1. Go to the crs-web\WebContent\Widgets-vendor\Properties directory.
    2. Open the generated MyWidgetText.properties for editing. By default, the file includes the following property:
      WidgetTypeDisplayText_identifier=displayName
    3. Add the translatable text for your widget into the file.
    4. Save your file.
    5. Repeat the preceding steps to edit the MyWidgetText_en_US.properties file to add translatable text for the United States English language.
    6. 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
Include all of the assets that are not shared between multiple widgets in the code package for your widget. This includes any JSP, JavaScript, and CSS files.
  1. 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.

  2. Optional: If an image is required by your custom widget for display in the storefront, include the image within the crs-web\WebContent\Widgets-vendor\images directory.
  3. 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 - crs-web\WebContent\Widgets-vendor\com.vendor.commerce.store.widgets.identifier\javascript
    • For store-level widgets - crs-web\WebContent\store\Widgets-vendor\om.vendor.commerce.store.widgets.identifier\javascript
    If the JavaScript file is shared by multiple custom widgets, add the file into the following directory:
    • For site-level widgets - crs-web\WebContent\Widgets-vendor\Common
    • For store-level widgets - crs-web\WebContent\store\Widgets-vendor\Common
    If your widget is a site-level widget move the assets to the Common directory at the site-level.

    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.
    • crs-web\WebContent\widgetdir\com.ibm.commerce.store.widgets.CatalogEntryRecommendation\javascript\CatalogEntryRecommendation.js
  4. 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 file path.
    • For site-level widgets - crs-web\WebContent\Widgets-vendor\Common
    • For store-level widgets - crs-web\WebContent\store\Widgets-vendor\Common
    If your widget is a site-level widget move the assets to the Common directory at the site-level.
  5. 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}"/>