Deliver a Knockout with
your APEX Applications

Jorge Rimblas

Jorge Rimblas

Senior APEX Consultant

  • Oracle DB since 1995
  • APEX since it was HTMLDB in 2004
  • Always involved in web technologies
  • jrimblas in OTN Forums
  • Contributor to
    "Expert Oracle Application Express, 2nd Edition"
    with "Themes & Templates" chapter

Age: 14 years!
Staff: 80+ employees
60 consultants/developers
APEX Solutions: 12 Years!
Largest APEX practice in North America
Oracle Center of Excellence

 

Agenda

  • Why?
  • What is KnockoutJS?
  • Data Binding
  • Two-Way Data Binding
  • Using with APEX
  • More APEX examples

Why?

Solid Track Record

Used by

Portal

Library

Not a framework

jQuery is a library

Good news for APEX

Dynamic Actions

More dynamic than

Dynamic Actions!

What is

?

Knockout is a JavaScript library that helps you to create rich, responsive display and editor user interfaces with a clean underlying data model.

* Source knockoutjs.com

Declarative Bindings

Automatic UI Refresh

Dependency Tracking

Templating

* Source knockoutjs.com

Declarative Bindings

select * from emp where empno = :empno
<span data-bind="text: empno"></span>
function emp() {
  this.empno = 7839;
}
<span data-bind="text: empno"></span>

JavaScript ViewModel contains data

function emp() {
  this.empno = 7839;
  this.ename = 'KING';
  this.job   = 'PRESIDENT';
  this.sal   = 5000;
}
<span data-bind="text: empno"></span>
<span data-bind="text: ename"></span>
<span data-bind="text: job"></span>

JavaScript ViewModel contains data

function emp() {
  this.empno = 7839;
  this.ename = 'KING';
  this.job   = 'PRESIDENT';
  this.sal   = 5000;
}

var viewModel = new emp();

ko.applyBindings(viewModel);

Automatic UI Refresh

...JavaScript...

ko.applyBindings();

Two-Way

Data Bind

observables

function empModel(data) {
  this.empno = data.empno;
  this.ename = ko.observable(data.ename);
  this.job   = ko.observable(data.job);
  this.sal   = ko.observable(data.sal);
}

observables

ko.observable()
ko.observableArray()

Dependency Tracking

Dependency Tracking

computed

  self.total = ko.computed(function() {
    return parseInt(self.val1()) +
           parseInt(self.val2());
  }, self);

Dependency Tracking

subscritions

self.val.subscribe(function(newVal) {
    self.save_value(self);
  }.bind(self));
apex.server.process(...)

Templating

// Static template name
<div data-bind="template: { name: 'personListTemplate', data: employees }"></div>
// Template determined by a function
<div data-bind="template: { name: selectedTemplate} "></div>

Dynamic Template

Templating

<script type="text/ko-template" id="personListTemplate">
<ul data-bind="foreach: people">
  <li data-bind="text: name"></li>
</ul>
</script>
<script type="text/ko-template" id="personTableTemplate">
<table>
<thead><tr><th>Name</th><th>Salary</th></tr></thead>
<tbody data-bind="foreach: people">
<tr>
  <td><span data-bind="text: name"></span></td>
  <td><span data-bind="text: sal"></span></td>
</tr>
</tbody>
</table>
</script>

KnockoutJS
and
APEX

Demo p10

Include the library

// APEX 18.1
#IMAGE_PREFIX#libraries/oraclejet/4.2.0/js/libs/knockout/knockout-3.4.0.js

APEX 18.1

// APEX 5.1
#IMAGE_PREFIX#libraries/oraclejet/2.0.2/js/libs/knockout/knockout-3.4.0.js

APEX 5.1

Demo p10

ko pre-rendered plugin

Playing Nice with APEX

#APP_IMAGES#knockout-pre-rendered.min.js

Add "init" binding

data-bind="init, textInput: val1"

Demo p12

Add "foreachInit" binding for looping

data-bind="foreachInit: products"

// or with template somewhere else on page

data-bind="foreachInit: { name: 'productTemplate', data: products }"


Demo p20

<script type="text/ko-template" id="productTemplate">
  <li data-bind="text: name"></li>
</script>

Adding "foreachInit" to the correct parent

var $rowContainer = $(this.triggeringElement).find(".t-Report-report tbody");

// Add ko foreach bind
$rowContainer.attr("data-bind",
                   "foreachInit: { name: 'productTemplate', data: products }");

Demo p20

Demo

Q&A

Deliver a Knockout with
your APEX Applications

Jorge Rimblas

Twitter: @rimblas