Using the Oracle JET Common Model and Collection Framework

The Oracle JET Common Model and Collection API provides a collection-of-records object model that includes classes for bringing external data into an Oracle JET application and mapping the data to the application’s view model.

Topics:

About the Oracle JET Common Model and Collection API

The Oracle JET Common Model and Collection API provides a collection-of-records object model that includes the following classes:

  • oj.Model: Represents a single record from a data service such as a REST service

  • oj.Collection: Represents a set of data records and is a list of oj.Model objects of the same type

  • oj.Events: Provides methods for event handling

  • oj.KnockoutUtils: Provides methods for mapping the attributes in a oj.Model or oj.Collection object to Knockout observables for use with component ViewModels

oj.Model and oj.Collection include client-side API that provides one way to bring external data into an Oracle JET application. oj.KnockoutUtils provides the map() method to map the attributes in a model object or the attributes of all models in a collection object to the application's view data model.

About Oracle JET Data Binding and Knockout

Knockout provides bindings between components as well as binding data from a ViewModel to components or HTML elements in an Oracle JET application. Knockout is an integral part of Oracle JET's framework and is included in the Oracle JET distribution.

The Oracle JET Model and Collection API includes the KnockoutUtils class which contains the map() method to convert the attributes in a model object (or the attributes of all models in a collection object) into Knockout observables for use with components' ViewModels.

The example below maps the data collection to the tasks ViewModel.

renderTaskViews = function(tasksData) {
    this.tasks = oj.KnockoutUtils.map(data);
}

To bind UI components in Oracle JET applications to the data model, the Oracle JET components support Knockout's data-bind attribute, both for standard and Oracle JET UI components. For additional information about working with Oracle JET UI components, see Understanding Oracle JET User Interface Basics.

<ul data-bind="foreach: tasks">
  <li data-bind="text: name"></li>
</ul>
<div data-b

For additional information about Knockout, see http://www.knockoutjs.com.

Using the Oracle JET Common Model and Collection API

To use a Model or Collection class, an application must extend oj.Model or oj.Collection to create a foundation object to represent a data record or list of records from its data service. The application provides the data service's URL used for fetching and updating task records (when a task record's ID is appended), along with various options giving users the ability to map data service records to their client-side ViewModel and vice versa.

To use the Oracle JET Common Model and Collection API:

  1. Add JavaScript code to your application that extends oj.Model.

    The following script shows a simple example of extending oj.Model to create a model object which defines a TaskRecord. In this example, the data is returned from the REST service at the indicated URL. The parse and parseSave callbacks parse the data and map the attributes received from the REST service to desired ViewModel attribute names.

    var TaskRecord = oj.Model.extend({
                                      url: "http://RESTServerIP:port/ADFjs-Tasks-context-root/resources/ojet/tasks",
                                      parse: parseTask
                                      parseSave: parseSaveTaskRecord});
     
     
    /**
     * Callback to map attributes returned from RESTful data service to desired view model attribute names
     */
    parseTask = function (response) {
        return {Priority: response['PRIORITY'], TaskType: response['TASK_TYPE'],
                Severity: response['SEVERITY'],id: response['TASK_ID'], Summary: response['SUMMARY']};
    };
     
    /**
     * Callback to map view model attributes back to RESTful data service record attribute names on create or update
     */
    parseSaveTaskRecord = function (record) {
        return {PRIORITY: record['Priority'], TASK_TYPE: record['TaskType'],
                SEVERITY: record['Severity'], TASK_ID: record['id'], SUMMARY: record['Summary']};
    };
    
  2. Add JavaScript code to your application that extends oj.Collection.

    The following code example creates a collection object for its entire data set (or list) of task records and ties that to a specific instance of a task record model. The fetch() method tells the collection to go to the data service and asynchronously retrieve the data services' data set using the given URL, through jQuery AJAX calls. The application's success callback method is invoked when the call successfully returns and the collection has been populated with model records.

    var task = new TaskRecord();
    task.on("all", onChangeEventHandler, this);
     
    // Create a base object "class" for the entire task dataset 
    var TaskCollection = oj.Collection.extend({
                                               url: "http://RESTServerIP:Port/Tasks-context-root/resources/ojet/tasks",
                                               model: task,
                                               initialize: function () { // Perform collection initialization here });
     
    // Create a specific instance for the tasks.  This will be filled with instances of the
    // model "task" for each record when the data is retrieved from the data service
    var tasks = new TaskCollection();
     
    // Get the tasks from the server, and call the success: function when finished for further application processing
    tasks.fetch({success:function (collection, response, options) {
                                        tasksData = collection;
                                        renderTaskViews(tasksData);
                                     }});
    
    // Called when any attribute changes on any task model object
    onChange = function() {
    };
    
  3. Bind the returned data collection to a Knockout ViewModel to make it ready for consumption by one or more components on the application page.

    The following code sample maps the tasks Collection object to the renderTaskViews view using the oj.KnockoutUtils.map() function.

    renderTaskViews = function(tasksData) {
        // self.tasks is the Knockout view model structure
        this.tasks = oj.KnockoutUtils.map(data);
        var self = this;
    }
    
  4. Add code to the application's index.html or main page that consumes the Knockout ViewModel.

    The following code examples shows a simple table that is defined with four columns: Priority, Severity, ID, and Owner. The data-bind data property binds the tasks collection to the ViewModel using Knockout.

    <table id="taskTable" summary="Task Table"
           data-bind="
                  wijgrid:
                  {
                   data: tasks,
                         allowPaging: true, showColumnHeader: true,
                         ensurePxWidth: true, pageSize: 10,
                         pagerSettings: { mode: 'numericFirstLast', pageButtonCount: 5},
                         columns:
                         [{dataKey: 'Priority', width: '10%', cellFormatter: priorityCellFormatter},
                         {dataKey: 'Severity', width: '10%', cellFormatter:severityCellFormatter},
                         {dataKey: 'ID', width: '6%' }, {dataKey: 'Summary', width: '35%' }, {dataKey: 'Status', width: '12%' },
                         {dataKey: 'Owner', width: '12%'}, {dataKey: 'Tags', width: '15%'}, {visible: false}, {visible: false}, {visible: false}, {visible: false}, {visible: false}, {visible: false}],
                         selectionChanged: handleSelectionChanged
                  }">
    </table>
    

For a complete list of Oracle JET Common Model and Collection API properties and functions, see the oj.Model and oj.Collection API documentation.