Start tracking your progress
Trailhead Home
Trailhead Home

Explore Page and Component Type Controllers, JSON, and Scripts

Learning Objectives

After completing this unit, you’ll be able to:
  • List three development elements you can use to create Page Designer page and component types.
  • List the JSON file naming convention.
  • Explain how controllers are used for Page Designer pages and components.
  • Describe the difference between how B2C Commerce uses JSON and JavaScript files for page and component types.

Introduction

Vijay Lahiri, the Cloud Kicks developer, appreciates that Page Designer’s development landscape requires only a few essential elements. Controllers, JSON, and script files are the most important file types beneath the surface. There’s more on the visual elements, such as ISML, HTML, and CSS later.

Controllers run the show, while JSON and script files work the details. Page type JSON files describe the regions of the page where Vijay can place components. Component type JSON files describe the attributes that he defines for using the component type, and possibly the regions within the component type.

Each JSON file has a comparable script file that includes a render function to return the markup for the page, the results of which must be a string. Always give the JSON and script files the same name, except for their extension, and put them in the same folder.

Controllers

Controllers are server-side scripts that handle storefront requests. They manage the flow of control in your application, and create instances of models and views to process each storefront request and generate an appropriate response. For example, clicking a category menu item or entering a search term triggers a controller that renders a page.

A storefront controller calls the dw.experience.PageMgr API to render pages, components and regions. You can use the controller to create a URL to Page Designer pages. For example, Vijay can use the URL to link to a page from a Cloud Kicks marketing email. He can also use the URL to add a link to the page from the global header or footer or main navigation of the storefront.

JSON

Always place JSON files in the following directories of the custom cartridge, or a subdirectory within them.

  • Page types: <your_cartridge>/cartridge/experience/pages
  • Component types: <your_cartridge>/cartridge/experience/components

The JSON file name can include only alphanumeric or underscore characters. If you put the meta definition file into a subdirectory within the /experience/pages or /experience/components directories, the names of the levels in the subdirectory must also use only alphanumeric or underscore characters.

Tip

Tip

See the Infocenter for schema files that describe the JSON formatting.

Page: homepage.json

Here’s what the homepage.json looks like.

{
 "name":"Homepage",
 "description":"A storefront homepage.",
 "region_definitions":[
    {
      "id":"header",
      "name":"Name",
      "description":"Header of the homepage",
          "max_components":1
    },
    {
      "id":"main",
      "name":"Main",
      "description":"Main area of the homepage",
      "component_type_exclusions":[
          {"type_id":"banner"}
      ]
    },
    {
      "id":"footer",
      "name":"Footer",
      "description":"Footer of the homepage",
      "max_components":1
      }
    ]
}

It has three regions: header, main, and footer.

The layout of a page with a header, main, and footer regions.

  • The header and footer regions display only one component at a time, as specified by max_components = 1.
  • The region_definition for the main region does not include a max_components value, which means that the main region can display multiple components.
  • The main region uses component_type_exclusion to specify that components of type banner are not allowed in the main region.

The max_components value restricts the number of components rendered for a region at a time, but the region can contain multiple components. Vijay can employ different components for different customers on different schedules. For example, a banner region can show a different component in the spring than in the summer.

Component: banner.json

The banner.json file defines three attributes that the merchandiser can set: an image file, alt text, and size. In Page Designer, the attributes appear in groups. For example, the attributes defined in this file appear in the visual editor in a group called Banner Image Configuration.

{
 "name": "Banner",
 "description": "A banner.",
 "group": "content",
 "attribute_definition_groups": [
   {
    "id":"image",
    "name":"Banner Image Configuration",
    "description":"You can define the image file, size and alt text for the banner image."
    "attribute_definitions":[
     {
       "id": "image",
       "name": "Banner Image",
       "description": "The image shown by the banner.",
       "type": "file",
       "required": true
     },
     {
       "id": "alt",
       "name": "Banner Image Alt Text",
       "description": "The image alt text shown by the banner.",
       "type": "string",
       "required": false
     },
     {
       "id":"size",
       "name":"Size",
       "description":"The banner size.",
       "type":"enum", "values":["small","medium","large"],
       "required":true,
       "default_value":"medium"
     }
     ]
   }
 ],
 "region_definitions": []
} 

Script Files

As Vijay learned earlier, a script file must have the same name as its matching meta definition file, but with a .js extension. The script file name can include only alphanumeric or underscore characters and must be in the same folder as its corresponding meta definition file.

The script file includes a render function that returns the markup for the page. Vijay can assemble the markup using any process he wants, as long as the result is a string. Typically, the render function calls an ISML template to which it passes information about the page or component type and its content. If you use an ISML template, you must use the dw.util.Template API to render the markup from it.

Tip

Tip

Don’t use dw.template.ISML because it doesn't return a string, and it writes the markup to the response stream right away.

User Decorators

Vijay wants to implement various strategies for using decorators with Page Designer pages. For example, he can write the script file for a page type so that he can pass in a custom decorator as a parameter when the page is rendered, or fall back to a default decorator defined in the script. He can also write a controller that renders the page so that a different decorator is used based on the value of a certain condition.

Page: homepage.js

Vijay takes a look at the homepage.js page. Here’s what it looks like.

'use strict';
var Template = require('dw/util/Template');
var HashMap = require('dw/util/HashMap');
/**
 * Render logic for the page.
 */
module.exports.render = function (context) {
   var model = new HashMap();
   // add parameters to model as required for rendering based on the given context (dw.experience.PageScriptContext):
   // * context.page (dw.experience.Page)
   // * context.renderParameters (String)
   // * context.content (dw.util.Map)
 return new
Template('experience/pages/promopage').render(model).text;
};

The context object that’s passed to the render function is of type dw.experience.PageScriptContext and provides access to these:

  • context.page: Currently rendered page
  • context.renderParameters: Parameters passed to PageMgr.renderPage(pageID, parameters)
  • context.content: Attributes set in the custom logic (not defined by the merchant)

Component: banner.js

Then he looks at banner.js, one of the components he wants to use.

'use strict';
var Template = require('dw/util/Template');
var HashMap = require('dw/util/HashMap');
/**
 * Render logic for the component.
 */
module.exports.render = function (context) {
   var model = new HashMap();
   // add parameters to model as required for rendering based on the given context
 (dw.experience.ComponentScriptContext):
   // * context.component (dw.experience.Component)
   // * context.content (dw.util.Map)
 return new
Template('experience/assets/banner').render(model).text;
};

This file uses the context object, which is passed to the render function. It’s of typedw.experience.ComponentScriptContext and provides access to these:

  • context.component: The currently rendered component.
  • context.componentRenderSettings: Render settings provided by the hosting region. You can override the render settings passed from the region with settings specific to the component.
  • context.content: Attributes as defined in the meta definition file for the component and then configured by the merchandiser in Page Designer (or as defined in custom logic).

Good JavaScript

Vijay uses the npm script to make sure his JavaScript adheres to the repository’s guidelines. He enters these commands before committing his code:

npm install

npm run lint

Next Steps

In this unit, you took a look at the code underlying Page Designer page and component types, including controllers, JSON, and scripts. The next unit covers the ISML, HTML, and CSS.