Step 13: Render a Component in an Inline Frame

The sample so far has shown a local component rendered in-line in the page. You can also choose to render a component in an inline frame.

For example, you may choose to render a component in an inline frame if your component does non-omnipotent updates to the page, which requires you to re-create the page whenever properties change. In addition, remote components are always rendered in an inline frame.

The samples in this section are taken from the files created for you when you choose the Create a component that renders in an iframe option when creating a local component. You can, however, take these set of files and host them on your remote server so they apply equally to remote components.

Similarities Between Inline Frame and Non-Inline Frame Components

Settings Panel

Because the Settings panel is always placed into the page in an inline frame, the code for the Settings panel doesn't change regardless of whether the component uses an inline frame or not. You’ll create the same Settings panel code for both use cases.

Sites SDK API

The SDK API is the same for both use cases. You’ll use the same code to raise triggers, listen for actions, and get and set property values. While certain properties may not be applicable in both cases (for example, you can't set the "height" property for a component that doesn’t use an inline frame) the API remains the same. Therefore, you can copy the code between both of these types of components and the example code discussed in this tutorial will work for both cases.

Differences Between Inline Frame and Non-Inline Frame Components

File Structure and Dependencies

When you select Create a component that renders in an iframe when creating a local component, you will see the following files created for you:
<component name>
    assets
        css
            app-styles.css
        js
            jquery.mn.js
            knockout.mn.js
            sites.min.js
        render.html
        settings.html
    appinfo.json
    _folder_icon.jpg

These files are created to allow you to immediately run your component in an inline frame on the page. The main differences between this structure and that of a standard local component are:

  • JavaScript dependencies:

    • You are getting a complete copy of these files so your component will run. These files are required for the sample inline frame component to run. You can add and remove the content of this directory based on your requirements.

    • Because everything under the assets directory for your component is pushed to a public site when the component is published, everything in the js directory will be available both in Site Builder and at runtime.

    • Note: These files are created for ease of use. You should look at consolidating these files in the theme or in another public location rather than create separate versions of these files for each of your inline frame components.

  • render.html:

    • This is a full HTML document as opposed to the render.js file for standard components, which is an AMD module.

Component "Height" Management

One of the issues in using an inline frame is the height management of the inline frame itself. If you get this wrong, you will see scroll bars appearing for the component on the page, which you may or may not want.

In order to manage the height of the inline frame, the component must tell the page how tall it wants the inline frame to be. With remote components, you may be dealing with cross-domain issues, so you must use Sites SDK messaging to ask the page to set the inline frame to the required height after the component has rendered on the page. This is done by using the SitesSDK.setProperty('height', {value}) API. (SeeOracle Content and Expeience SDKs.)

For example, create the setHeight function and a custom binding handler to call it when the component has rendered on the page.

  • Update height function:

    // set the height of the iFrame for this App
    self.setHeight = function () {
    // use the default calculation or supply your own height value as a second parameter
    SitesSDK.setProperty('height');
    };
  • Knockout custom binding handler to call setHeight whenever the component is rendered on the page or a property changes:

    ko.bindingHandlers.sampleAppSetAppHeight = {
      update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        // create dependencies on any observables so this handler is called whenever it changes
        var imageWidth = viewModel.imageWidth(),
            imageUrl = viewModel.imageUrl(),
            titleText = viewModel.titleText(),
            userText = viewModel.userText();
    
      // re-size the iFrame in the Sites page now the template has rendered
      // Note: If you still see scrollbars in the iframe after this, it is likely that CSS styling in your app is the issue
      viewModel.setHeight();
     }
    };
  • Template update to call binding handler:

    <div data-bind="sampleAppSetAppHeight: true"></div>

Trigger and Action Registration

While the trigger/action registration for components that are not in inline frames is located in the appinfo.json file, for inline frame components, the component itself is responsible for providing this information. This is done using these two APIs:

SitesSDK.subscribe('GET_ACTIONS', self.getAppActions);
SitesSDK.subscribe('GET_TRIGGERS', self.getAppTriggers);

Here’s an example of using these APIs.

    // Register TRIGGERS meta-data
    SampleAppViewModel.prototype.getAppTriggers = function (args) {
      var triggers = [{
        "triggerName": "imageClicked",
        "triggerDescription": "Image clicked",
        "triggerPayload": [{
          "name": "payloadData",
          "displayName": "Trigger Payload Data"
        }]
      }];

      return triggers;
    };

    // Register ACTIONS meta-data
    SampleAppViewModel.prototype.getAppActions = function (args) {
      var actions = [{
        "actionName": "setImageWidth",
        "actionDescription": "Update the image width",
        "actionPayload": [{
          "name": "imageWidth",
          "description": "Image Width in pixels",
          "type": {
            "ojComponent": {
            "component": "ojInputText"
            }
          },
          "value": ""
        }]
      }];

      return actions;
    };

Access to Theme Styles

Because the component is rendered in an inline frame, it doesn't have access to the styles available in the theme. The Sites SDK provides an API to retrieve these styles so they can be applied to elements within the inline frame.

This topic is explored more in Step 14: Use Custom Styles When the Component is Rendered in an Inline Frame.

Mixed HTTPS Versus HTTP Protocol

Because Oracle Content Management uses the HTTPS protocol, all resources referenced within the page also must use HTTPS. Resources include the base .html file that will be rendered in the inline frame along with all the files that it references.

This resource requirement applies mostly to remote components, however, you must be aware of this constraint. Resources for local components using inline frames are provided by the Oracle Content Management server, so these components already use a matching protocol.

Continue to Step 14: Use Custom Styles When the Component is Rendered in an Inline Frame.