Oracle JET - Refer to ViewModel from HeaderTemplate in ojTable - and easier debugging of KnockOut code image 9

Oracle JET – Refer to ViewModel from HeaderTemplate in ojTable – and easier debugging of KnockOut code

While developing a Oracle JET application against APIs on Oracle Service Bus interacting to JD Edwards and Oracle Transportation Management, we ran into a challenge. In the table (ojTable) that we had included in a page, we wanted to have column filters – fields in each column header where the user can enter a filter criteria for that column. The ojTable component supports the headerTemplate property (next to a rowTemplate and a footerTemplate). A headerTemplate is defined separately from the ojTable and can contain various components as well as script.

Our table and template were defined as follows:

       <script type="text/html " id="country_temp">
        <th>
        <div class="inline-form">
           <input id="a" name="b" data-bind="ojComponent: {
                                component: 'ojInputText', value: country}" }
                                <p>Country</p>
                                </div>
         </th>
    </script>
    <table id="customertable" summary="Customer List" aria-label="Customer Table" data-bind="ojComponent: {component: 'ojTable',
                                data: datasource,
                               selectionMode: {row: 'single'},
                                columnsDefault: {sortable: 'enabled'},
                                columns: [{headerText: 'Customer Number',   field: 'CustomerNumber'}, 
                                          {headerTemplate: 'country_temp',   field: 'Country'}
                                         ],
                                            rootAttributes: {'style':'height: 300px; width:100%;'}}">
    </table>

It was our intent to have changes in the inputText in the column header – the filter field – immediately picked up and processed; in the ViewModel, code should be triggered by the change and should filter the data in the ArrayTableDataSource bound to the ojTable. The ViewModel has an observableArray on which the ArrayTableDataSource is based – by manipulating that observableArray we can get our table to refresh. The ViewModel also contains a KnockOut observable called country. It is this observable that we want to databind the inputText in the headerTemplate to. By subscribing our own function to this country observable we hope to be triggered when the user enters a value in the inputText and react in style.

The ViewModel:

define(['ojs/ojcore' ,'knockout','ojs/ojmodel','ojs/ojtable','ojs/ojInputText', 'ojs/ojdatacollection-common'

], function(oj, ko) {

function contentViewModel() {

var self = this;

self.data = [{CustomerNumber : 123, Country: 'DK'},{CustomerNumber : 456, Country: 'NL'}];

self.dataSource = new oj.ArrayTableDataSource( ko.observableArray(self.data),

{idAttribute: 'CustomerNumber'}

);

self.country = ko.observable('text');

self.country('XX'); // default value

console.log('Value of country '+self.country());

self.country.subscribe(

(function(newValue) {

console.log('does this work?'+newValue);

})

);

}

return contentViewModel;

});

This is where our real challenge arose: we did not know how to data bind the inputText in the headerTemplate to the ViewModel that underpins the view template and also contains the ArrayTableDataSource that the ojTable is bound to. A simple binding to country does not work, trying to use the $headerContext variable that is available in the headerTemplate did not help us either and Googling provided no solution.

We then reached out to our friends in the world – and got an almost instantaneous response from Geertjan Wielenga. He pointed us to the $module variable that is available in the view and also inside the headerTemplate. This variable references the ViewModel. We could now easily create the data binding on $module.country

 <script type="text/html " id="country_temp">
        <th>
        <div class="inline-form">
           <input id="a" name="b" data-bind="ojComponent: {
                                component: 'ojInputText', value: $module.country}" }
                                <p>Country</p>
                                </div>
         </th>
    </script>

and from now on any change in the inputText triggered our own silly function.

image

 

Geertjan also sent us this screenshot of the Knockout Window in NetBeans, showing the complete, understandable context data available in KnockOut objects:

knockout-window-netbeans

 

We (actually my colleague Cindy Berghuizen) then also found the Chrome Plugin Knockoutjs context debugger that also seems helpful in learning about the actual context available in our Knockout code in Oracle JET applications: it shows the knockout context & data for the selected dom node in a sidebar of the elements pane.

image

 

Resources

JET Cookbook on ojTable: http://www.oracle.com/webfolder/technetwork/jet/jetCookbook.html?component=table&demo=basicTable

Some docs on headerTemplate http://www.oracle.com/webfolder/technetwork/jet/jsdocs/oj.ojTable.html#initializer-section

Relevant thread on Community Forum: https://community.oracle.com/message/13705036#13705036

Chrome Plugin: Knockoutjs Context Debugger

YouTube demo on NetBeans support for Oracle JET and the integration between NetBeans and Chrome: https://www.youtube.com/watch?v=GX1doCIqhp8