4 Use RequireJS for Modular Development

Oracle JET includes RequireJS, a third party JavaScript library that you can use in your app to load only the Oracle JET libraries you need. Using RequireJS, you can also implement lazy loading of modules or create JavaScript partitions that contain more than one module.

About Oracle JET and RequireJS

RequireJS is a JavaScript file and module loader that simplifies managing library references and is designed to improve the speed and quality of your code.

RequireJS implements the Asynchronous Module Definition (AMD) API which provides a mechanism for asynchronously loading a module and its dependencies.

Oracle JET's modular organization enables app developers to load a subset of needed features without having to execute require() calls for each referenced object. Each Oracle JET module represents one functional area of the toolkit, and it typically defines more than one JavaScript object.

You do not have to use RequireJS to reference Oracle JET libraries, but it is required if you plan to use Oracle JET's internationalization or data visualization components in your app. The Oracle JET download includes the RequireJS library, and it is used by default in the Oracle JET Starter Templates and Cookbook examples.

For more information about RequireJS, see http://requirejs.org.

About Oracle JET Module Organization

The Oracle JET modules are listed in the following table with description and usage tips. Use this table to determine which modules you must load in your app. Where your app can directly interact with a module API, the available objects that the module returns also appear in the table. Your app would typically call functions on the returned object or instantiate new objects via the constructor function. For more information about module loading in Oracle JET apps, see API Reference for Oracle® JavaScript Extension Toolkit (Oracle JET) - JET Module Loading Overview.

Note:

Certain functionality that had been previously available from the now deprecated ojcore, ojvalidation-base, ojvalidation-datetime, and ojvalidation-number modules is provided by refactored modules that return their own object. The table indicates which modules have been refactored. You should explicitly import needed modules in the dependency list of your require function to use its classes.

Oracle JET Module Refactored Available Objects Description When to Use

ojs/ojmodel

No

Collection

Events

Model

OAuth

URLError

Classes of the JET Common Model

Other than OAuth, all Oracle JET Common Model classes should be replaced by the Oracle JET RESTDataProvider class.

ojs/ojknockout-model

No

KnockoutUtils

Utilities for integrating Oracle JET's Common Model into Knockout.js

Deprecated. Use the Oracle JET RESTDataProvider class.

ojs/ojcomponent

No

Varies by component
Oracle JET component modules. Examples include
  • ojs/ojbutton

  • ojs/ojtoolbar

  • ojs/ojtabs

Most Oracle JET components have their own module with the same name in lowercase and without hyphens as shown above, except for the following components:
  • oj-buttonset-*: ojs/ojbutton

  • oj-input-password: ojs/ojinputtext

  • oj-text-area: ojs/ojinputtext

  • oj-combobox-*: ojs/ojselectcombobox

  • oj-select-*: ojs/ojselectcombobox

  • oj-spark-chart: ojs/ojchart

  • oj-*-gauge: ojs/ojgauge

Use component modules that correspond to any Oracle JET component in your app.

ojs/ojknockout

No

ComponentBinding

Oracle JET data binding for global attributes of any HTML element in the user interface

Use when your app includes HTML elements (JET custom elements included) with databound global attributes (ones that use the : (colon) prefix) or that use the [[..]]/{{..}} syntax (for global attributes of custom elements).

ojs/ojcorerouter

No

urlParamAdapter, urlPathAdapter

CoreRouter, CoreRouterState

Class for managing routing in single page apps

Use if your single page app needs to manage routing.

ojs/ojmodule

No

ModuleBinding

Binding that implements navigation within a region of a single page app

Use if your single page app needs to manage navigation within a page region.

ojs/ojmodule-element

No

ModuleElementAnimation

Component that implements navigation within a region of a single page app

Use if your single page app needs to manage navigation within a page region.

ojs/ojmoduleanimations

No

ModuleAnimations

Used in conjunction with ojs/ojmodule-element. Adds animation support via CSS animation effects.

Use if your app adds animation effects.

ojs/ojcontext

Yes, from ojcore

BusyContext, Context

Class that exposes the BusyContext that keeps track of components that are currently animating or fetching data.

Use if your app needs to query the busy state of components on the page.

ojs/ojconfig

Yes, from ojcore

Config

Class for setting and retrieving configuration options.

Use if your app needs to set or retrieve app configuration details.

ojs/ojlogger

Yes, from ojcore

Logger

Utilities for setting up a logger and collecting logging information

Use if your app needs to define logger callback functions.

ojs/ojresponsiveutils

Yes, from ojcore

ResponsiveUtils

Utilities for working with responsive screen widths and ranges. Often used in conjunction with ojs/ojresponsiveknockoututils to create knockout observables that can be used to drive responsive page behavior.

Use if your app needs to work with responsive page design.

ojs/ojthemeutils

Yes, from ojcore

ThemeUtils

Utilities for getting theme information

Use if your app needs to know about the theme's fonts or the target platform.

ojs/ojtimeutils

Yes, from ojcore

TimeUtils

Utilities for time information

Use if your app needs to calculate the position of a given time point within a range.

ojs/ojtranslation

Yes, from ojcore

Translations

Service for retrieving translated resources

Use if your app needs to work with translated resources.

ojs/ojattributegrouphandler

No

AttributeGroupHandler, ColorAttributeGroupHandler, ShapeAttributeGroupHandler

Classes for managing attribute groups

Use if your app needs to generate attribute values from data set values (key value pairs).

ojs/ojknockouttemplateutils

No

KnockoutTemplateUtils

Utilities for converting Knockout templates to a renderer function that can be used in JET component renderer APIs

Use if your app needs to work with Knockout templates.

ojs/ojresponsiveknockoututils

No

ResponsiveKnockoutUtils

Utilities for creating Knockout observables to implement responsive page design

Use if your app needs to create observables for responsive page design.

ojs/ojswipetoreveal

No

SwipeToRevealUtils

Utilities for setting up and handling swipe to reveal on an offcanvas element

Use if your app needs to support the swipe gesture.

ojs/ojkeyset

No

KeySet, KeySetImpl, AllKeySetImpl

Class for working with selection items in ojTable, ojListView, and ojDataGrid components

Use if your app needs to work with selections as a set.

ojs/ojdiagram-utils

No

DiagramUtils

Utilities for working with a JSON object to support the ojDiagram component

Use if your app creates an ojDiagram component from a JSON object.

ojs/ojoffcanvas

No

OffcanvasUtils

Class for controlling off-canvas regions

Use if your app needs to manage off-canvas regions.

ojs/ojcube

No

Cube, CubeAggType, CubeAxis, CubeAxisValue, CubeCellSet, CubeDataValue, CubeHeaderSet, CubeLevel, DataColumnCube, DataValueAttributeCube

Classes for aggregating data values in ojDataGrid

Use if your app renders aggregated cubic data in an ojDataGrid component.

ojs/ojtypedataprovider

No

ArrayDataProvider, ArrayTreeDataProvider, CollectionDataProvider, DeferredDataProvider, FlattenedTreeDataProvider, IndexerModelTreeDataProvider, ListDataProviderView, PagingDataProviderView, TreeDataProviderView

FilterFactory

Data provider modules. Examples include:
  • ojs/ojarraydataprovider

  • ojs/ojcollectiondataprovider

  • ojs/ojtreedataprovider

Use if your app includes an Oracle JET component, and its data source is defined in one of the *DataProvider classes.

ojs/ojtimezonedata

No

no public class available

Time zone data

Use if you want to add time zone support to oj-input-date-time, oj-input-time, or converters.

ojconverter-color, ojconverter-datetime, ojconverter-number

Yes, from ojvalidation-base, ojvalidation-datetime, or ojvalidation-number

ColorConverter, converterDateTime, converterColor

Color, date, and time conversion services.

Use if your app needs to support conversion services.

ojvalidator-daterestriction, ojvalidator-datetimerange, ojvalidator-length, ojvalidator-numberrange, ojvalidator-regexp, ojvalidator-required

Yes, from ojvalidation-base, ojvalidation-datetime, or ojvalidation-number

DateRestrictionValidator, DateTimeRangeValidator, LengthValidator, NumberRangeValidator, RegExpValidator, RequiredValidator

Date and number validation services.

Use if your app needs to support validation services.

ojasyncvalidator-daterestriction, ojasyncvalidator-datetimerange, ojasyncvalidator-length, ojasyncvalidator-numberrange, ojasyncvalidator-regexp, ojasyncvalidator-required

Yes, from ojvalidation-base, ojvalidation-datetime, or ojvalidation-number

AsyncDateRestrictionValidator, AsyncDateTimeRangeValidator, AsyncLengthValidator, AsyncNumberRangeValidator, AsyncRegExpValidator,

Async date and number validation services.

Use if your app needs to support async validation services.

About RequireJS in an Oracle JET App

Oracle JET includes the RequireJS library and sample bootstrap file in the Oracle JET download.

The code below shows excerpts of the main-template.js bootstrap file distributed with the Oracle JET base distribution in the appRootDir\node_modules\@oracle\oraclejet\dist\js\libs\oj\ directory. Typically, you place the bootstrap file in your app's js directory and rename it to main.js . The comments in the code describe the purpose of each section. The sections that you normally edit are highlighted in bold.

/**
 * Example of Require.js boostrap javascript
 */
(function () {
    requirejs.config({
      // Path mappings for the logical module names
      paths: {

      },

      // This section configures the i18n plugin. It is merging the Oracle JET built-in translation
      // resources with a custom translation file.
      // Any resource file added, must be placed under a directory named "nls". You can use 
      // a path mapping or you can define a path that is relative to the location 
      // of this main.js file.
      config: {
        ojL10n: {
          merge: {
            // 'ojtranslations/nls/ojtranslations': 'resources/nls/myTranslations'
          }
        },
        text: {
          // Override for the requirejs text plugin XHR call for loading text 
          // resources on CORS configured servers
          // eslint-disable-next-line no-unused-vars
          useXhr: function (url, protocol, hostname, port) {
            // Override function for determining if XHR should be used.
            // content omitted for brevity
            // Return true or false. true means "use xhr", false 
            // means "fetch the .js version of this resource".
            return true;
          }
        }
      }
    });
  }());
  
  /**
   * A top-level require call executed by the app.
   * Although 'ojcore' and 'knockout' would be loaded in any case (they are specified as dependencies
   * by the modules themselves), we are listing them explicitly to get the references to the 'oj' and 'ko'
   * objects in the callback.
   *
   * For a listing of which JET component modules are required for each component, see the specific component
   * demo pages in the JET cookbook.
   */
  require(['ojs/ojcore', 'knockout', 'jquery', 'ojs/ojknockout', 'ojs/ojbutton', 'ojs/ojtoolbar', 'ojs/ojmenu'], 
     // add additional JET component modules as needed
    // eslint-disable-next-line no-unused-vars
    function (oj, ko, $) { // this callback gets executed when all required modules are loaded
        // add any startup code that you want here
    }
  );

You can use RequireJS in a regular app as shown, or you can use RequireJS with oj-module element to define view templates and viewModels for page sections in a single-page app. For example, the Oracle JET Starter Templates use the oj-module element with RequireJS to use a different view and viewModel when the user clicks one of the navigation buttons.

For additional information about the Oracle JET Starter Templates, see About the Starter Templates. For more information about using ojModule and templates, see Create Single-Page Apps.

Use RequireJS in an Oracle JET App

To use RequireJS in your app, edit the bootstrap file to add the Oracle JET modules you need. You can also add your own modules as needed for your app code.

If needed, install Oracle JET and install RequireJS at http://requirejs.org.

To use RequireJS in an Oracle JET app:

  1. In the bootstrap file or your app scripts, in the require() definition, add additional Oracle JET modules as needed.
  2. Add any scripts that your app uses to the require() definition and update the function(ko) definition to include the script.
  3. Add any app startup code to the callback function.
  4. If your app includes resource bundles, enter the path to the bundle in the merge section.

Here's an example of the steps in order.

Your app uses the Oracle JET Common Model integrated with Knockout and includes an oj-dialog. Add the highlighted modules to your bootstrap file or app script.
require(['knockout', 'ojs/ojmodel', 'ojs/ojknockout-model','ojs/ojdialog'],
  function(ko) // obtaining a reference to the oj namespace
  {
  }
);

Then, to use a script named myapp.js, add the highlighted code to your require() definition.

require(['myapp', 'knockout', 'ojs/ojmodel', 'ojs/ojknockout-model', 'ojs/ojdialog'],
  function(myapp, ko) // obtaining a reference to the oj namespace
  {
  }
);

Next, you have a Knockout binding call for an element named dialogWrapper. Add that to the callback function.

require(['myapp', 'knockout', 'ojs/ojmodel', 'ojs/ojknockout-model', 'ojs/ojdialog'],
  function(myapp, ko) // obtaining a reference to the oj namespace
  {
    ko.applyBindings(new app()/*View Model instance*/,
                     document.getElementById('dialogWrapper'));
  }
);

Finally, you have a translations bundle, which you add to the merge section.

config: {
  ojL10n: {
    merge: {
      'ojtranslations/nls/ojtranslations': 'resources/nls/myTranslations'
    }
  }
}

For more information about module loading in Oracle JET apps, see API Reference for Oracle® JavaScript Extension Toolkit (Oracle JET) - JET Module Loading Overview.

Add Third-Party Tools or Libraries to Your Oracle JET App

You can add third-party tools or libraries to your Oracle JET app. The steps to take will vary, depending on the method you used to create your app.

If you used command-line tooling to scaffold your app, you will install the library and make modifications to appRootDir/src/js/path_mapping.json . If you created your app using any other method and are using RequireJS, you will add the library to your app and update the RequireJS bootstrap file, typically main.js.

Note:

This process is provided as a convenience for Oracle JET developers. Oracle JET will not support the additional tools or libraries and cannot guarantee that they will work correctly with other Oracle JET components or toolkit features.

To add a third-party tool or library to your Oracle JET app, do one of the following:

  • If you created your app with command-line tooling, perform the following steps.

    1. In your main project directory, enter the following command in a terminal window to install the library using npm:

      npm install library-name --save

      For example, enter the following command to install a library named my-library:

      npm install my-library --save
    2. Add the new library to the path mapping configuration file.

      1. Open appRootDir/src/js/path_mapping.json for editing.

        A portion of the file is shown below.

        {
          "baseUrl": "js",
          "use": "local",
        
          "cdns": {
            "jet": "https://static.oracle.com/cdn/jet/15.1.0/default/js",
            "css": "https://static.oracle.com/cdn/jet/15.1.0/default/css",
            "config": "bundles-config.js"
            },
            "3rdparty": "https://static.oracle.com/cdn/jet/15.1.0/3rdparty"
          },
        
          "libs": {
        
            "knockout": {
              "cdn": "3rdparty",
              "cwd": "node_modules/knockout/build/output",
              "debug": {
                "src": "knockout-latest.debug.js",
                "path": "libs/knockout/knockout-#{version}.debug.js",
                "cdnPath": "knockout/knockout-3.x.x"
              },
              "release": {
                "src": "knockout-latest.js",
                "path": "libs/knockout/knockout-#{version}.js",
                "cdnPath": "knockout/knockout-3.x.x"
              }
            },
        
        ... contents omitted
      2. Copy one of the existing entries in "libs" and modify as needed for your library.

        The sample below shows modifications for my-library, a library that contains both minified and debug versions.

        ...
         "libs": {
        
            "my-library": {
              "cwd": "node_modules/my-library/dist",
              "debug": {
                "src": "my-library.debug.js",
                "path": "libs/my-library/my-library.debug.js"
              },
              "release": {
                "src": "my-library.js",
                "path": "libs/my-library/my-library.js"
              }
            },
        ...

        In this example, cwd points to the location where npm installed the library, src points to a path or array of paths containing the files that will be copied during a build, and path points to the destination that will contain the built version.

        Note:

        If the existing entry that you copy to modify includes "cdn": "3rdparty", remove it from the newly-created entry for your library. This line references the Oracle JET third-party area on the content distribution network managed by Oracle. Your library won't be hosted there and keeping this line will cause a release build to fail at runtime by mapping the path for your library to a non-existent URL.

        If you use a CDN, add the URL to the CDN in the entry for cdnPath.

  • If you didn’t use the tooling to create your app, perform the following steps to add the tool or library.

    1. In the app’s js/libs directory, create a new directory and add the new library and any accompanying files to it.

      For example, for a library named my-library, create the my-library directory and add the my-library.js file and any needed files to it. Be sure to add the minified version if available.

    2. In your RequireJS bootstrap file, typically main.js, add a link to the new file in the path mapping section and include the new library in the require() definition.

      For example, add the highlighted code below to your bootstrap file to use a library named my-library.

      requirejs.config({
        // Path mappings for the logical module names
        paths: 
        {
          'knockout': 'libs/knockout/knockout-3.x.x',
          'jquery': 'libs/jquery/jquery-3.x.x.min',
          ... contents omitted
          'text': 'libs/require/text',
          'my-library': 'libs/my-library/my-library
        },
        require(['knockout', 'my-library'],
        function(ko) // this callback gets executed when all required modules are loaded
        {
            // add any startup code that you want here
        }
      );
      

      For additional information about using RequireJS to manage your app's modules, see Use RequireJS for Modular Development.

Troubleshoot RequireJS in an Oracle JET App

RequireJS issues are often related to modules used but not defined.

Use the following tips when troubleshooting issues with your Oracle JET app that you suspect may be due to RequireJS:

  • Check the JavaScript console for errors and warnings. If a certain object in the oj namespace is undefined, locate the module that contains it based on the information in About Oracle JET Module Organization or the Oracle JET Cookbook and add it to your app.

  • If the components you specified using Knockout.js binding are not displayed and you are not seeing any errors or warnings, verify that you have added the ojs/ojknockout module to your app.

About JavaScript Partitions and RequireJS in an Oracle JET App

RequireJS supports JavaScript partitions that contain more than one module.

You must name all modules using the RequireJS bundles option and supply a path mapping with the configuration options.

requirejs.config(
  {
    bundles:
    {
      'commonComponents': ['ojL10n', 'ojtranslations/nls/ojtranslations',
                           'ojs/ojknockout', 'ojs/ojcomponentcore',
                           'ojs/ojbutton', 'ojs/ojpopup'],
      'tabs': ['ojs/ojtabs', 'ojs/ojconveyorbelt']    }
  }
);

In this example, two partition bundles are defined: commonComponents and tabs.

RequireJS ships with its own Optimizer tool for creating partitions and minifying JavaScript code. The tool is designed to be used at build time with a complete project that is already configured to use RequireJS. It analyzes all static dependencies and creates partitions out of modules that are always loaded together. The Oracle JET team recommends that you use an optimizer to minimize the number of HTTP requests needed to download the modules.

For additional information about the RequireJS Optimizer tool, see http://requirejs.org/docs/optimization.html.

For additional information about optimizing performance of Oracle JET apps, see Optimize Performance of Oracle JET Apps.