Referencing Fragments in Extensions

In an extension, you can reference fragments in the same extension as well as fragments defined in dependent extensions. When an extension references a fragment defined in a dependent extension, the dependent extension name is prepended to the fragment name.

To reference a fragment defined in a dependent extension, the fragment's JSON descriptor must include the "referenceable": "extension" property.

{
  "description": "A product list fragment",
  "title": "Product List Fragment",
  "referenceable": "extension",
...
}

In an extension, you can reference fragments:

  • In a page in your extension's App UI,
  • In a section template that extends a dynamic container,
  • In a field or form template for your extension's dynamic tables and forms,
  • In a field or form template that extends a dynamic form or table in a dependent extension.

Here's an example of a page in an extension referencing a fragment in a dependent extension (in this example, extA is the name of the dependent extension):

<oj-dialog id="newProductDialogDynamic" title="New Product" initial-visibility="hide">
  <div slot="body" style="border:2px">
    <oj-defer>
      <oj-vb-fragment id="createProd1" name="extA:create-product">
      </oj-vb-fragment>
    </oj-defer>
  </div>
</oj-dialog>

Example 1-54 Reference a fragment in a page

In this example, the fragment products-list is defined in a dependent extension (extA). A page defined in an App UI of an extension can include the products-list fragment using a prefix before the fragment name: extA:products-list).

<oj-vb-fragment id="prod-list" name="extA:products-list" bridge="[[ vbBridge ]]">
  <oj-vb-fragment-param name="catalog" value="[[ 'US' ]]"></oj-vb-fragment-param>
</oj-vb-fragment>

To bind an event fired by the fragment onto a listener in the calling page of the extension, the event in the fragment must be part of the interface. It must also have the 'propagationBehavior' set to 'container'. For details, see Custom Fragment Events.

This example shows the 'saveproduct' event declared by the fragment 'products-list':

"interface": {
  "events": {
    "saveproduct": {
      "description": "fired when a product has been created. The mutated product is fixed up in a local array and returned",
      "propagationBehavior": "container",
      "payloadType": {
        "data": [
          {
            "id": "string",
            "name": "string",
            "unitPrice": "number",
            "productCategory": "string"
          }
        ],
        "message": "string"
      }
    }
  }
}

A page in the extension that references the above fragment from the dependent extension can bind the event to a listener on the page using the on-<eventname> attribute:

<oj-vb-fragment id="prods" name="extA:products-list" bridge="[[ vbBridge ]]"
  on-saveproduct="[[ $page.listeners.onSaveProduct ]]">
 
</oj-vb-fragment>

WARNING:

It is important that the event name be lowercase or camelCase with no hyphens as defined by Web Component DOM event naming conventions.

Example 1-55 Reference a fragment in a dynamic container template

Generally, the only artifacts in a fragment that can be extended are its model and the JavaScript code. However, if a page in a dependent extension contains a dynamic container, an extension could override the dynamic container's section template(s) to then reference a fragment defined in the dependent extension.

In the following example, the section template references the fragment 'incidents-list' in a dependent extension (using the dependent extension's name as the prefix before the fragment name: extA:incidents-list).

<!-- dynamic container section template -->
<template id='tmplExtB'>
  <oj-vb-fragment id="incs-list" name="extA:incidents-list" bridge="[[ vbBridge ]]">
    <oj-vb-fragment-param name="technicianId" value="[[ $application.user.userId ]]"></oj-vb-fragment-param>
  </oj-vb-fragment>
</template>

It's important to note that the fragment 'incidents-list' must be marked as 'referenceable' so that a dependent extension can use it.

{
  "description": "A incidents list layout fragment",
  "title": "Incidents List Fragment",
  "referenceable": "extension",
...
}

To bind an event fired by a referenced fragment to a listener in the calling page template, the event in the fragment must be part of the interface. It must also have the 'propagationBehavior' set to 'container'. For details, see Custom Fragment Events.

"interface": {
  "events": {
      "updatedincidentmessage": {
        "description": "fired when an incident has been updated. The mutated incident data is provided in payload",
        "propagationBehavior": "container",
        "payloadType": {
          "data": {
            "id": "string",
            "problem": "string",
            "priority": "string",
            "status": "string",
            "customer": {
              "id": "string"
            }
          }
        }
      }
    }
  }
}

The template in the extension (that references the fragment) can bind the event to a listener using the "on-<eventname>" attribute.

<oj-vb-fragment id="incs-list" name="extA:incidents-list" bridge="[[ vbBridge ]]"
       on-updatedincidentmessage="[[ $listeners.updateMessageBarWithUpdatedIncident ]]">
</oj-vb-fragment>

WARNING:

It is important that the event name be lowercase or camelCase with no hyphens as defined by Web Component DOM event naming conventions.

Example 1-56 Reference a fragment in a dynamic layout form template

A fragment can be referenced from field and form templates used in dynamic forms. When doing so, it's important to pass the context property setup by the layout component ($dynamicLayoutContext) to the fragment as a parameter. This context is an umbrella property that contains all other dynamic component-related context variables, such as $value and $metadata.

In the following example of a form template, the form is rendered using the fragment dynamic-form-template-employee:

<template id="formTemplateSimple">
  <oj-vb-fragment id="formTemplateSimple_EmpFrag" name="dynamic-form-template-employee" bridge="[[ vbBridge ]]">
      <oj-vb-fragment-param name="$dynamicLayoutContext"
                            value="[[ $dynamicLayoutContext ]]"></oj-vb-fragment-param>
      </oj-vb-fragment>
</template>

The fragment dynamic-form-template-employee stores the layout property in a variable defined in the fragment. Within the fragment markup (HTML), it can be used in an expression like $variables.dynamicLayoutContext.fields... (or whichever sub-properties you may need in your template markup) to access sub-properties of the layout context:

<oj-input-text :id="[[ $fragment.info.id + '-empname']]"
  label-hint="Employee Name"
  value="{{ $variables.dynamicLayoutContext.fields.firstName.value  }}"></oj-input-text>

$dynamicLayoutContext

The $dynamicLayoutContext context property needs to be configured when a fragment is used in form or field templates in layout components. The $dynamicLayoutContext allows:

  • To write back to 'dynamic layout managed' objects.

    Some fragments are intended to be used both within form templates and field templates.

    Particularly when used within a field template, it can be very desirable to be able to not only read a value provided by the dynamic component field, but also to write back to the same. The $dynamicLayoutContext property enables this without requiring you to configure a fragment event to notify the parent of the changed value.

    Using $dynamicLayoutContext, you can pass this context property provided by the layout component into the fragment as a reference (using an input parameter as shown in the example above). You can then bind the input component / 'value' property in the fragment to read and write to this variable. By doing this, any changes in the input value is automatically known by the parent layout.

  • To consolidate context properties in one basket.

    Before fragments were used in layout component templates, authors would have used any number of the context properties (like $fields, $value etc.) that the parent layout exposed, and bind those to the components they use in the templates. But after adding support for fragments inside templates, a new container boundary is introduced, so these context properties are now no longer available/bindable directly by the components inside the fragment. In order to expose these context properties to fragment components, this top-level context property was introduced.