Examples of Accessing Global Functions in Extensions

The following examples describe the level of access available to global functions from extension artifacts.

Example 1-67 extA is a top level extension that defines a functions JavaScript extAUtils.js

extA defines its own functions files, under ui/self/resources. Additionally, it also defines functions under an App UI (appUi-A) and under appUi-A/pages.

  • extA has no dependencies on other extensions
  • extA defines a public extAUtils.js that can be accessed by downstream extensions.
    • Additionally, UI artifacts such as some-page.json can access the extAUtils.
extA/
  ui/
    self/
      resources/
        functions/
          extAUtils.js
          functions.json // { extAUtils: { referenceable: "extension" } }


      applications/
        appUIA/
          .../
            some-page.json


  manifest.json // { dependencies: [] }

In the example above, some-page.json can have an imports section like this:

{
  "imports": {
    "modules": {
      "AUtils": {
        "path": "self:$functions/extAUtils"
      }
    }
  }
}

The imported module in the example above can be accessed using the expression ({{ $page.modules.AUtils.someMethod() }}).

Example 1-68 extA1 depends on extA and defines functions (both private and public)

  • extA1 has a dependency on extA
  • extA1 defines a private a1PrivateUtils.js that can be imported only by extA1 containers.
    • For example, a1-form-fragment.json can import the private module.
  • It also defines a public extA1Utils.js that can be imported by containers in the current and downstream extensions.
extA1/
  ui/
    self/
      resources/
        functions/
          private/
            a1PrivateUtils.js
          public/
            extA1Utils.js
          functions.json


      fragments/
        a1-form/
          a1-form-fragment.json
          a1-form-fragment.js
          a1-form-fragment.html


  manifest.json // { dependencies: [ extA ] }

In the example above, a1-form-fragment.json can import the private module and have an imports section. If a module is not declared here, it's not automatically available. For example, 'extA1Utils' is not defined here, so it cannot be used.

{
  "imports": {
    "modules": {
      "A1PrivateUtils": {
        "path": "self:$functions/a1PrivateUtils"
      },
      "extAUtils": {
        "path": "extA:$functions/extAUtils"
      }
    }
  }
}

Some fragment markup can call a method exposed on the private utils:

<oj-bind-text text="{{ $modules.A1PrivateUtils.titleCase($variables.name)) }}"/>

<oj-bind-text text="{{ $modules.extAUtils.region($variables.code) }}"/>

Because extA1 depends on extA, it can also refer to public functions from extA.

Example 1-69 extB depends on extA and extA1 and defines a functions JS extBUtils.js

  • extB defines a layout 'buttons'
  • extB defines its own global functions (extBUtils)
  • extB also extends the fragment 'a1-form-fragment' from extA1
extB/
  dynamicLayouts/
    self/
      buttons/
        layout.json

  ui/
    self/
      resources/
        functions/
          extBUtils.js
          functions.json
        js/


    ext-A1/

      fragments/
        a1-form/
          a1-form-fragment-x.json
          a1-form-fragment-x.js


  manifest.json // dependencies: [ extA, extA1 ]

buttons/layout.json references the fragment from extA1. It can call the public extAUtils and extA1Utils, in addition to the global functions extBUtils. This could be defined in layout.json:

{
  "imports": {
    "modules": {
      "extA1Utils": {
        "path": "extA1:$functions/extA1Utils"
      },
      "BUtils": {
        "path": "self:$functions/extBUtils"
      }
    }
  }
}

The layout.html could define a template that uses a fragment from extA1. The fragment, because it's defined by extA1, can internally call a 'functions' module that is private to extA1.

<template id="formTemplateSimple">

    <oj-vb-fragment name="extA1:a1-form"
                    bridge="[[vbBridge ]]">
      <oj-vb-fragment-param name="dynamicLayoutContext"
                            value="[[ $dynamicLayoutContext ]]"></oj-vb-fragment-param>

      <oj-vb-fragment-param name="foo" value="[[ $modules.BUtils.titleCase($layout.variables.lucy) ]]">
      </oj-vb-fragment-param>

    </oj-vb-fragment>

</template>

extB also extends the fragment from extA1. This means the fragment-x will need to explicitly define all imports it needs from the current extension and any of its upstream extensions. The use of $base is not recommended for accessing imports of the base container, because the exact list of imports that are accessible by the extended artifact cannot be easily determined, nor can it be complete. For example, the a1-form-fragment.json from extA1 did not import extA1Utils. Likewise, it imports local resources that should be hidden for the current extension.

It is recommended that authors explicitly import the modules they need. A sample imports on a1-form-fragment-x.json might look like this:

{
  "imports": {
    "modules": {
      "extA1Utils": {
        "path": "extA1:$functions/extA1Utils"
      }
    }
  }
}

Example 1-70 extZ extends layout from extB and also depends on extA1

  • extZ extends the 'buttons' layout from extB and also defines its own 'zippers' layout.
  • extZ also overrides some pages from the unified app.
  • extZ also defines its own functions, in addition to having a 'functions' folder at the App UI level (resources/functions) folder under appUiZ (see the example below).
    • While there appears to be a functions.json defined at the App UI resources level, these cannot be imported into the App UI using the $functions scheme. These files can be imported into the App UI pages using the current schemes for importing such files.
extZ/
  dynamicLayouts/
    extB/
      buttons/
        layout-x.json
        
    self/
      zippers/
        layout.json

  ui/
    self/
      applications/
        appUiZ/
          app.json
          pages/
            shell-page.html
            shell-page.json

          resources/
            functions/
              appUiZtils.js
              functions.json

      resources/
        functions/
          extZUtils.js
          functions.json

    base/
      pages/
        root/
          first-page-x.json
      app-flow-x.json
      
  manifest.json // dependencies: [ extB, extA1 ]

The following sections detail the level of access for functions and the $modules usage in the various Visual Builder containers.

Functions Access and $modules Usage in extZ/dynamicLayouts/extB/buttons/layout-x

When layout-x is an extension of a layout from extB, it should be possible to import extB's functions, as well as the dependency extension (extA1).

extA is not specified in the dependencies list, so its functions cannot be imported.

Note:

An extension must explicitly import the resources it needs, and not use $base to access the imports set up by the artifact it extends.

extZ defines its own functions, so layout-x can import any of these.

{
  "imports": {
    "modules": {
      "extBUtils": {
        "path": "extB:$functions/extBUtils"
      },
      "extA1Utils": {
        "path": "extA1:$functions/extA1Utils"
      },
      "ZUtils": {
        "path": "self:$functions/extZUtils"
      }
    }
  }
}

Functions Access and $modules Usage in extZ/dynamicLayouts/self/zippers/layout-x

The files allowed in the previous section are also allowed here.

Functions Access and $modules Usage in extZ/ui/self/applications/appUiZ/pages/shell-page

The files allowed in the previous section are also allowed here.

Functions Access and $modules Usage in extZ/ui/base/pages/app-flow-x.json

The files allowed in the previous section are also allowed here.