Using Oracle JET to Create SCS Component – Part 2

This is a long overdue Part 2 of my earlier post about using Oracle JET for developing custom components fro Sites. The team is very busy completing next major release that will add new capabilities to Oracle Content and Experience Cloud as well as Sites which prevented me from publishing Part 2 in time. Here it is. Stay tuned for the new release!

JQuery and Running No Conflict Mode

At the end of Part 1, cards in the JET sample should render on Sites page. However, if you click on the card, they won’t flip. If you looked at the JS console, you would have seen:

 >viewModel.js:36 Uncaught TypeError: $ is not a function(…)

This is because Sites runs with JQuery in “no conflict” mode which allows customers to run their own version of JQuery in the page layout and also extend this version of JQuery with plugins of their choice..

Depending on your requirements, you’ll either include your own version of JQuery in the page layout or use the built-in version of JQuery that is included as part of Sites.

For this sample, we’ll update the viewModel.js of the ‘JETCCA’ component to use the built-in version of JQuery:

  • Navigate to the ‘JETCCA’ component you created
  • Navigate  to the “assets/composites/demo-card” and open viewMode.js file
  • Update the require at the top of the file to the following.
define(['knockout', 'jquery'],
function (ko, $) {

The code above requires in the eversion of jQuery that is packaged as part of Sites and assigns it to local “$” parameter for use within the module. After you saved and sync viewMode.js file, open the site page to which you added ‘JETCCA’ component. In Preview mode, you should be able to click on one of the cards to see it flip and show the details the employee.

Mapping Oracle JET CCA events to Sites Triggers

Now we’ll look at hooking up inter-component communication between Oracle JET components and another Sites component.

Oracle JET Composite defines the following optinos in the the CCA .json file:

  • Properties
  • Events
  • Methods

The “Properties” map to the input parameters for the component which allows you to create entries in the Sites component Settings panel that you can pass across JET CCA component.

“Events” are HTML 5 custom events that the CCA component raises.  You will need to create a wrapper for these events to convert them to Sites Actions and have them take part in Sites’ triggers & actions.

The demo-card CCA component doesn’t come with any events so we’ll first create one:

  • Open up viewModel.js file:
  • Store the properties that were passed in so we can easily access them. For that  change the context.props.then() to:
context.props.then(function(properties) {
 self.properties = properties;
 if (properties.name) {
 var initials = properties.name.match(/\b\w/g);
 self.initials = (initials.shift() + initials.pop()).toUpperCase();
 }
 if (properties.workNumber)
 self.workFormatted = formatPhoneNumber(properties.workNumber);
 });
  • Create the following function to call from a ‘click’ event:
/**
 * Raise "Show Card Details" event
 * @param {MouseEvent} event The click event
 */
self.raiseShowCardDetails = function (data, event) {
 var ccaElem = event.target || event.srcElement,
 evt = new CustomEvent('selectCard', {
 detail: self.properties,
 bubbles: true // the default is false
 });

 ccaElem.dispatchEvent(evt);
};
  • Open up view.html file
  • Call the above function when the user clicks on the front of the card:
<code class="java plain">
<div </code><code class="java keyword">class</code><code class="java plain">=</code><code class="java string">"front-side"</code> <code class="java plain">data-bind=</code><code class="java string">"click: raiseShowCardDetails"</code><code class="java plain">></code>

As a result, whenever the user clicks on the front of the card, it will call the “raiseShowCardDetails” function, which raises the “selectCard” custom event. Now that you have the event raised, you should register the event with the JET CCA component.

Open up the metadata.json file and add the following entry:

"events": {
 "selectCard": {
 "description": "Card Selected",
 "detail": {
 "name": {
 "description": "The employee's full name.",
 "type": "string"
 },
 "avatar": {
 "description": "The url of the employee's image.",
 "type": "string"
 },
 "workTitle": {
 "description": "The employee's job title.",
 "type": "string"
 },
 "workNumber": {
 "description": "The employee's work number.",
 "type": "number"
 },
 "email": {
 "description": "The employee's email.",
 "type": "string"
 },
 "backgroundImage": {
 "description": "The url of the background to use for the employee's card",
 "type": "string"
 }
 }
 },
 "bubbles": true
}

This tells anyone consuming the demo-card that it can raise a “selectCard” event and describes the payload passed with the event.

To convert the event into a Sites action, you need to create a listener for the event and then raise a Sites Action:

  • Open up render.js file for your component
  • Create a Knockout custom binding handler that will listen for the event once the component has been added to the page. This listener calls “viewModel.raiseTrigger” passing in the detail information from the event
ko.bindingHandlers.registerCCADemoCardEvents = {
 init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
 var eventName = 'selectCard';
 viewModel.ccaDemoCardEventListener = element.addEventListener(eventName, function (e) {
 // raise the SCS trigger
 viewModel.raiseTrigger(eventName, e.detail || {});
 }, true);
 }
};

Now add the “raiseTrigger” code to your viewModel:

At last, you need to make sure the custom binding you created is called, so bring up the render.html file and add the custom binding (replace the first <div> with the following:

<code class="java plain">
<div </code><code class="java keyword">class</code><code class="java plain">=</code><code class="java string">"oj-flex oj-sm-flex-items-initial"</code> <code class="java plain">data-bind=</code><code class="java string">"attr: {id: divId}, registerCCADemoCardEvents: true"</code><code class="java plain">></code>

Now that you’ve caught the CCA event and caused it to raise a Sites trigger, you need to let Sites know about the trigger. To do this:

Download the “appinfo.json” file that is created for the “JETCCA” component under the top level folder for the component. Open it up and add replace the “triggers” section with the following:

"triggers": [
 {
 "triggerName": "selectCard",
 "triggerDescription": "Card Selected",
 "triggerPayload": [
 {
 "name": "name",
 "displayName": "The employee's full name."
 },
 {
 "name": "avatar",
 "displayName": "The url of the employee's image."
 },
 {
 "name": "workTitle",
 "displayName": "The employee's job title."
 },
 {
 "name": "workNumber",
 "displayName": "The employee's work number."
 },
 {
 "name": "email",
 "displayName": "The employee's email."
 },
 {
 "name": "backgroundImage",
 "displayName": "The url of the background to use for the employee's card"
 }
 ]
 }
],

Now that you’ve created the CCA event and converted it to a Sites trigger, you can wire the CCA event to any action within Sites.

  • Sync all the files that you update in ‘JETCCA‘ component and refresh the browser window to pick up a new builder session – some changes to appInfo.json file may be cached
  • Take the Sites page with ‘JETCCA‘ component into Edit mode and  delete it. Drop the ‘JETCCA‘ component onto the page.
  • Bring up the settings panel for the component and select the “Link” tab.
  • At this point you should see a “Card Selected” trigger listed. If you don’t see it, validate that you have the correct entry in appinfo.json and it is uploaded.
  • Click on the “Card Selected” link
  • Choose the “Show Alert” Action on the left and drop it on the right
  • Select “The employee’s full name” from the drop-down
  • Click “OK” on the dialog and close the Settings panel
  • Now, click on one of the cards
  • At this point, an alert will display with the employees name
  • If you click on the back of the card, nothing happens since you only created the CCA event on the front of the card

Mapping Oracle JET CCA Methods as Sites Actions

As with Oracle JET CCA events, JET CCA methods can be mapped to Sites Actions. Any function on the CCA viewModel can potentially be a Oracle JET CCA event so we can use the existing “flipCard” function to map to a Sites Action.

The first step is to register the action in the CCA meta-data.

Open up metadata.json and add the following to the metadata (the below entry notes that there is a “flipCard” method that can be called and that it takes two parameters: “mode” and “event“:

"methods": {
"flipCard": {
"model": {},
"event": {
"type": "click"
}
}
}

Now that you’ve registered the method, we can create a Sites Action to call that method:

  • Open up render.js file and add the following to the view model code in render.js (This code listens for a call to execute the “flipCards” Sites action and then calls the “flipCard” method on each of the underlying CCA Components created for the “this.employees” data above):
// Convert custom component Actions into CCA component methods
this.executeMyAction = $.proxy(function (args) {
if (args.action && args.action.actionName === 'flipCards') {
for (var i = 0; i < this.employees.length; i++) {
var card = $('#' + this.divId + 'card' + i)[0];
card.flipCard({}, {
"type": "click"
});
}
}
}, this);
SitesSDK.subscribe('EXECUTE_ACTION', this.executeMyAction);
  • Open up render.html file and change the demo-card entry to the following code (This allows the action code to identify each instance of the CCA Component on the page. Normally you’d only have a single parent CCA component but, for this sample, we’re creating multiple instances of the card CCA component):
<demo-card class="oj-flex-item" name="{{name}}" avatar="{{avatar}}" work-title="{{title}}"
work-number="{{work}}" email="{{email}}" background-image="{{backgroundImage}}" data-bind="attr: { id: $parent.divId + 'card' + $index() }">
</demo-card>
  • Open appInfo.json file and change the “actions” entry to register the “flip card” action.
"actions": [
{
"actionName": "flipCards",
"actionDescription": "Flip the cards",
"actionPayload": []
}
]

Now when you bring up the triggers & actions dialog, if there is a ‘JETCCA‘ component on the page, it will list the “Flip the cards” action. To validate the action, you can use an SCS button to call it to “flip the cards”

  • Sync all your files
  • Take the Sites page into Edit mode and delete any existing ‘JETCCA‘ component
  • Re-drop your ‘JETCCA‘ component onto the page
  • Drop Button component onto the page and then bring up the Settings panel against the button
  • Change the caption to “Flip cards”
  • Click on the “Link” tab and select “Trigger actions” from the drop down
  • Click on the “Button clicked” trigger
  • Expand the “JETCCA” entry on the left. If it doesn’t exist, check syntax in your appInfo.json file and ensure it’s uploaded.
  • Select the “Flip the cards” event and drop onto the right. Click “OK” and close the Settings panel
  • Switch to “Preview” mode. Click on the “Flip cards” button. At this point, all the cards should flip

Known Issues

There are several issues with the approach described above that we will be addressing in next releases of Sites:

  • Packaging:  You probably noticed that you had to load on your Sites page a number of quite large JET libraries. We are working on a better model to package JET libraries that will be  made available via Require to the Sites page and loadded from a CDN.
  • Styles: when you switch to “view” mode from “edit” you will see the list of cards change.  This is because it hasn’t loaded in the Oracle JET styles in “view” mode.  To get around this, you can load in the CSS you previously uploaded: ‘css!./oj/oj-alta-notag-min.css‘.
  • Styles: When you flip the card, the font size & margin may not be compatible with the page. You need to update the styles.css file of the CCA component to reflect the styles already in the page.

Completed Samples:

 

 

Leave a comment