Вы находитесь на странице: 1из 100

Closing the gap

between APEX and JET


Alan Arentsen
Closing the gap
between APEX and JET
Alan Arentsen
alanarentsen.blogspot.com @ alanarentsen
CAUTION
JAVASCRIPT
X-ING
http://oracle.com/goto/jet
JET UI Components

JET Routing
View

System
jQuery UI hammer.js Sass

RequireJS
knockout.js ViewModel

JET Common Model Model


Client Browser
Server side
RESTful WS WebSocket Business Service

 " Data
APEX JET

Multi page application Single page application

Code is mainly in database Code is all on webserver

Pages are rendered from
 Pages are loaded from



database webserver
PL/SQL JavaScript

Low-Code (declarative) Deep Dive (imperative)


database page designer static files

deep dive low-code deep dive


JET UI Components

JET Routing
System
jQuery UI hammer.js Sass

RequireJS
knockout.js

JET Common Model


     RequireJS is a JavaScript file
                                         and module loader.
config
initialization

modules
Config
requirejs.config(
{
baseUrl: 'js',
paths:
{
'knockout' : 'libs/knockout/knockout-3.4.0.debug',
'jquery' : 'libs/jquery/jquery-3.1.1',
'jqueryui-amd' : 'libs/jquery/jqueryui-amd-1.12.0',
'promise' : 'libs/es6-promise/es6-promise',
'hammerjs' : 'libs/hammer/hammer-2.0.8',
'ojdnd' : 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
'ojs' : 'libs/oj/v4.0.0/debug',
'ojL10n' : 'libs/oj/v4.0.0/ojL10n',
'ojtranslations': 'libs/oj/v4.0.0/resources',
'text' : 'libs/require/text',
'signals' : 'libs/js-signals/signals',
'customElements': 'libs/webcomponents/custom-elements.min',
'proj4' : 'libs/proj4js/dist/proj4-src',
'css' : 'libs/require-css/css',
}
});
Config
requirejs.config(
{
baseUrl: 'js',
paths:
{
'knockout' : 'libs/knockout/knockout-3.4.0.debug',
'jquery' : 'libs/jquery/jquery-3.1.1',
'jqueryui-amd' : 'libs/jquery/jqueryui-amd-1.12.0',
'promise' : 'libs/es6-promise/es6-promise',
'hammerjs' : 'libs/hammer/hammer-2.0.8',
'ojdnd' : 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
'ojs' : 'libs/oj/v4.0.0/debug',
'ojL10n' : 'libs/oj/v4.0.0/ojL10n',
'ojtranslations': 'libs/oj/v4.0.0/resources',
'text' : 'libs/require/text',
'signals' : 'libs/js-signals/signals',
'customElements': 'libs/webcomponents/custom-elements.min',
'proj4' : 'libs/proj4js/dist/proj4-src',
'css' : 'libs/require-css/css',
}
});
Config
requirejs.config(
{
baseUrl: 'js',
paths:
{
'knockout' : 'libs/knockout/knockout-3.4.0.debug',
'jquery' : 'libs/jquery/jquery-3.1.1',
'jqueryui-amd' : 'libs/jquery/jqueryui-amd-1.12.0',
'promise' : 'libs/es6-promise/es6-promise',
'hammerjs' : 'libs/hammer/hammer-2.0.8',
'ojdnd' : 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
'ojs' : 'libs/oj/v4.0.0/debug',
'ojL10n' : 'libs/oj/v4.0.0/ojL10n',
'ojtranslations': 'libs/oj/v4.0.0/resources',
'text' : 'libs/require/text',
'signals' : 'libs/js-signals/signals',
'customElements': 'libs/webcomponents/custom-elements.min',
'proj4' : 'libs/proj4js/dist/proj4-src',
'css' : 'libs/require-css/css',
}
});
Config
requirejs.config(
{
baseUrl: 'js',
paths:
{
'knockout' : 'libs/knockout/knockout-3.4.0.debug',
'jquery' : 'libs/jquery/jquery-3.1.1',
'jqueryui-amd' : 'libs/jquery/jqueryui-amd-1.12.0',
'promise' : 'libs/es6-promise/es6-promise',
'hammerjs' : 'libs/hammer/hammer-2.0.8',
'ojdnd' : 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
'ojs' : 'libs/oj/v4.0.0/debug',
'ojL10n' : 'libs/oj/v4.0.0/ojL10n',
'ojtranslations': 'libs/oj/v4.0.0/resources',
'text' : 'libs/require/text',
'signals' : 'libs/js-signals/signals',
'customElements': 'libs/webcomponents/custom-elements.min',
'proj4' : 'libs/proj4js/dist/proj4-src',
'css' : 'libs/require-css/css',
}
});
Config
requirejs.config(
{
baseUrl: 'js',
paths:
{
'knockout' : 'libs/knockout/knockout-3.4.0.debug',
'jquery' : 'libs/jquery/jquery-3.1.1',
'jqueryui-amd' : 'libs/jquery/jqueryui-amd-1.12.0',
'promise' : 'libs/es6-promise/es6-promise',
'hammerjs' : 'libs/hammer/hammer-2.0.8',
'ojdnd' : 'libs/dnd-polyfill/dnd-polyfill-1.0.0',
'ojs' : 'libs/oj/v4.0.0/debug',
'ojL10n' : 'libs/oj/v4.0.0/ojL10n',
'ojtranslations': 'libs/oj/v4.0.0/resources',
'text' : 'libs/require/text',
'signals' : 'libs/js-signals/signals',
'customElements': 'libs/webcomponents/custom-elements.min',
'proj4' : 'libs/proj4js/dist/proj4-src',
'css' : 'libs/require-css/css',
}
});
Initialization

require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',


'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton',
'ojs/ojtoolbar'],
function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
);
Initialization

require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',


'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton',
'ojs/ojtoolbar'],
function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
);

JavaScript Array
['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',
'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist',
'ojs/ojbutton', 'ojs/ojtoolbar' ]
Initialization

require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',


'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton',
'ojs/ojtoolbar'],
function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
);

JavaScript Function Expression


function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
Initialization

require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',


'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton',
'ojs/ojtoolbar'],
function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
);
Initialization

require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',


'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton',
'ojs/ojtoolbar'],
function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
);
Initialization

require(['ojs/ojcore', 'knockout', 'appController', 'ojs/ojknockout',


'ojs/ojmodule', 'ojs/ojrouter', 'ojs/ojnavigationlist', 'ojs/ojbutton',
'ojs/ojtoolbar'],
function (oj, ko, app) {
// this callback gets executed when all required modules are loaded
}
);
Modules

define(['ojs/ojcore', 'knockout', 'jQuery', 'ojs/ojknockout'],


function (oj, ko, $) {
// this callback gets executed when all required modules are loaded
}
);
Modules

define(['ojs/ojcore', 'knockout', 'jQuery', 'ojs/ojknockout'],


function (oj, ko, $) {
// this callback gets executed when all required modules are loaded
}
);

JavaScript Array
['ojs/ojcore', 'knockout', 'jQuery', 'ojs/ojknockout' ]
Modules

define(['ojs/ojcore', 'knockout', 'jQuery', 'ojs/ojknockout'],


function (oj, ko, $) {
// this callback gets executed when all required modules are loaded
}
);

JavaScript Function Expression


function (oj, ko, $) {
// this callback gets executed when all required modules are loaded
}
index.html

<script data-main="scripts/main" src="scripts/require/require.js"></script>

Load main.js after the require.js library

data-main="scripts/main"

index.html require.js main.js


s
ar
ye
s
th
on
m s
ek
we
ys
da
s
ur
ho
[require requirejs]/myjs/main.js

[require jet]/myjs/main.js
[require requirejs]/myjs/main.js

<script type="text/javascript"

src="/i/libraries/oraclejet/2.0.2/js/libs/require/require.js?v=5.1.3.00.05">

</script>

<script type="text/javascript" src="/myjs/main.js></script>


[require jet]/myjs/main.js

<script type="text/javascript"

src="/i/libraries/oraclejet/2.0.2/js/libs/require/require.js?v=5.1.3.00.05">

</script>

<script type="text/javascript"

src="/i/libraries/apex/minified/requirejs.jetConfig.js?v=5.1.3.00.05">

</script>

<script type="text/javascript" src="/myjs/main.js></script>


[require requirejs]/myjs/main.js
Config
url:
https://apexea.oracle.com/i18100032/libraries/apex/requirejs.jetConfig.js

browser console:
> require.s.contexts._.config
{waitSeconds: 7, baseUrl: "/i18100032/libraries/", paths: {…}, bundles: {…}, pkgs: {…}, …}
baseUrl: "/i18100032/libraries/"

bundles: {}

config: {ojL10n: {…}}
paths:
css : "./oraclejet/4.2.0/js/libs/require-css/css.min"

customElements: "./oraclejet/4.2.0/js/libs/webcomponents/custom-elements.min"

hammerjs : "./hammer/2.0.8/hammer-2.0.8.min"

jquery : "./jquery/3.1.1/jquery-3.1.1.min"

jqueryui-amd : "./oraclejet/4.2.0/js/libs/jquery/jqueryui-amd-1.12.0.min"

ojL10n : "./oraclejet/4.2.0/js/libs/oj/v4.2.0/ojL10n"

ojdnd : "./oraclejet/4.2.0/js/libs/dnd-polyfill/dnd-polyfill-1.0.0.min"

ojs : "./oraclejet/4.2.0/js/libs/oj/v4.2.0/min"

ojtranslations: "./oraclejet/4.2.0/js/libs/oj/v4.2.0/resources"

proj4 : "./oraclejet/4.2.0/js/libs/proj4js/dist/proj4"

promise : "./oraclejet/4.2.0/js/libs/es6-promise/es6-promise.min"

signals : "./oraclejet/4.2.0/js/libs/js-signals/signals.min"

text : "./oraclejet/4.2.0/js/libs/require/text"
Config
requirejs.config({

// Path mappings for the logical module names


baseUrl: apex_img_dir + "libraries/",
paths: {
"jquery" : "./jquery/2.2.3/jquery-2.2.3.min",
"jqueryui-amd" : "./oraclejet/2.0.2/js/libs/jquery/jqueryui-amd-1.11.4.min",
"ojs" : "./oraclejet/2.0.2/js/libs/oj/v2.0.2/" +
( dbg ? "debug" : "min" ),
"ojL10n" : "./oraclejet/2.0.2/js/libs/oj/v2.0.2/ojL10n",
"ojtranslations": "./oraclejet/2.0.2/js/libs/oj/v2.0.2/resources",
"text" : "./oraclejet/2.0.2/js/libs/require/text",
"promise" : "./oraclejet/2.0.2/js/libs/es6-promise/promise-1.0.0.min",
"hammerjs" : "./hammer/2.0.4/hammer-2.0.4.min",
'signals' : './oraclejet/2.0.2/js/libs/js-signals/signals.min',
"ojdnd" : "./oraclejet/2.0.2/js/libs/dnd-polyfill/
dnd-polyfill-1.0.0.min"
}
});
page designer static files

low-code deep dive


Initializer
page designer static files
main.js

low-code deep dive


DEM !
pros & cons
Pros
• Very Fast
• Lots of new features
• Minimal effort in APEX

Cons
• Side affects of JET CSS
• Does only work when APEX Item has 

the same base structure as the JET Element
pros & cons
Pros
• Very Fast
• Lots of new features
• Minimal effort in APEX

Cons
• Side affects of JET CSS
• Does only work when APEX Item has 

the same base structure as the JET Element
Knockout
page designer static files
main.js

low-code deep dive


DEM !
pros & cons
Pros
• Fast
• Flexible
• Lots of new features

Cons
• Side affects of JET CSS
• Every item is a APEX Region
pros & cons
Pros
• Fast
• Flexible
• Lots of new features

Cons
• Side affects of JET CSS
• Every item is a APEX Region
Does only work when APEX Item has 

the same base structure as the JET Element

items & regions


Every item is a APEX Region
Data Attribute
(with items)
page designer static files
main.js

low-code deep dive


Initialization of HTML element
$('#P1_SELECT_JET').ojSelect();

Add data attribute to HTML element


data-bind="ojComponent: {component: 'ojSelect'}"
DEM !
pros & cons
Pros
• Very Fast
• Very Flexible
• Lots of new features

Cons
• Side affects of JET CSS
• Does only work when APEX Item has 

the same base structure as the JET Element
page designer static files
main.js

low-code deep dive

data-bind="ojComponent:
$('#P1_SELECT_JET').ojSelect();
{component: 'ojSelect'}"
Data Attribute
(with regions)
page designer static files
main.js

low-code deep dive


HTML element with Knockout
<select data-bind="ojComponent: {component: 'ojSelect'}">
<option value="1">option 1</option>
<option value="2">option 2</option>
<option value="3">option 3</option>
<option value="4">option 4</option>
</select>

Add data attribute to HTML element


data-bind="ojModule: {name: 'select'}"
DEM !
pros & cons
Pros
• Very Fast
• Very Flexible
• Lots of new features
• High reusability of code
• Minimal effort in APEX
Cons
• Side affects of JET CSS
• No low-code
What have we learned till now?
don't put too much JavaScript in APEX

minimize efforts in APEX,


make it clear you use external JavaScript

make use of the JET modules and


JET components where possible
5.1.4.00.08

2.0.2
5.1.4.00.08

2.0.2 4.2.0
upgrade to JET 4.2.0
oraclejet.zip

&IMAGE_PREFIX. apex_img_dir
Config
url:
https://apexea.oracle.com/i18100032/libraries/apex/requirejs.jetConfig.js

browser console:
> require.s.contexts._.config
{waitSeconds: 7, baseUrl: "/i18100032/libraries/", paths: {…}, bundles: {…}, pkgs: {…}, …}
baseUrl: "/i18100032/libraries/"

bundles: {}

config: {ojL10n: {…}}
paths:
css : "./oraclejet/4.2.0/js/libs/require-css/css.min"

customElements: "./oraclejet/4.2.0/js/libs/webcomponents/custom-elements.min"

hammerjs : "./hammer/2.0.8/hammer-2.0.8.min"

jquery : "./jquery/3.1.1/jquery-3.1.1.min"

jqueryui-amd : "./oraclejet/4.2.0/js/libs/jquery/jqueryui-amd-1.12.0.min"

ojL10n : "./oraclejet/4.2.0/js/libs/oj/v4.2.0/ojL10n"

ojdnd : "./oraclejet/4.2.0/js/libs/dnd-polyfill/dnd-polyfill-1.0.0.min"

ojs : "./oraclejet/4.2.0/js/libs/oj/v4.2.0/min"

ojtranslations: "./oraclejet/4.2.0/js/libs/oj/v4.2.0/resources"

proj4 : "./oraclejet/4.2.0/js/libs/proj4js/dist/proj4"

promise : "./oraclejet/4.2.0/js/libs/es6-promise/es6-promise.min"

signals : "./oraclejet/4.2.0/js/libs/js-signals/signals.min"

text : "./oraclejet/4.2.0/js/libs/require/text"
Content Delivery Network (CDN)

Base url:
https://static.oracle.com/cdn/jet/v4.2.0/3rdparty/
DEM !
BE CAREFUL

charts regions
&
interactive grid
charts
might not work
BE CAREFUL

JET 2.0.2
&
lower version
JQuery
18.1.0.00.32

4.2.0
Composite Component
Architecture
(CCA)
JET Composite Component Architecture (CCA)

JET Composite Component

Metadata

HTML
JET Custom DOM Composite
Application Element Binding
JS

CSS
JET Composite Component Architecture (CCA)

JET Composite Component

Metadata

<my-composite-component attribute1="value1"
HTML
JET Custom DOM attribute2="value2"
Composite
Application Element attribute3="value3">
Binding
</my-composite> JS

CSS
JET Composite Component Architecture (CCA)

JET Composite Component

Metadata

<my-composite-component attribute1="value1"
HTML
JET Custom DOM attribute2="[[value2]]"
Composite
Composite
Application Element attribute3="{{value3}}">
Binding
Binding
</my-composite> JS

CSS
JET Composite Component Architecture (CCA)

JET Composite Component


main.js
Metadata

HTML
JET Custom DOM Composite
Application Element Binding
JS

CSS
CCA heaven
page designer static files
main.js

low-code deep dive


DEM !
Data
{ JS N}

select json_arrayagg(json_object(key 'name' value s.name,


key 'title' value s.title,
key 'work' value s.work,
key 'email' value s.email,
key 'avatar' value s.avatar))
from s4a_members s
{ JS N}
define(['ojs/ojcore'], function (oj) {
var employeesFactory = {
resourceUrl: 'https://apexea.oracle.com/pls/apex/adbc/hr/employees/',
// Create a single employee instance:
createEmployeeModel: function () {
Oracle var employee = oj.Model.extend({
REST Data Service urlRoot: this.resourceUrl,
idAttribute: "empno"
});
return new employee();
},
// Create a employees collection:
createEmployeesCollection: function () {
var employees = oj.Collection.extend({
url: this.resourceUrl,
model: this.createEmployeeModel()
});
return new employees();
}
};
return employeesFactory;
});
{ JS N}
apex.server.process ("MY_PROCESS",
{ x01 : "test",
pageItems: "#P1_DEPTNO,#P1_EMPNO"},
{ success : function( pData ) {
// do something here
}
});

apex.server.plugin (lAjaxIdentifier,
{ x01 : "test",
pageItems: "#P1_DEPTNO,#P1_EMPNO"},
{ refreshObject : "#P1_MY_LIST",
loadingIndicator: "#P1_MY_LIST",
success: function( pData ) {
// do something here
}
});
summery

[require jet]/myjs/main.js

data-bind="ojModule: {name: 'mymodule'}"

( data-bind="ojComponent: {component: 'ojSelect'}" )


summery
data-bind="ojComponent: {component: 'ojSelect'}"

<my-composite-component attribute1="value1"
attribute2="value2"
attribute2="[[value2]]"
attribute3="value3">
attribute3="{{value3}}">
</my-composite>

data-bind="ojModule: {name: 'mymodule'}"


summery
summery
reuse modules from JET applications

create your own HTML components (with CCA)

use parts of applications made with VBCS or JET in APEX

expand your APEX application with lots of new features instead of migrating to JET
!
www.database-consultancy.nl
Alan Arentsen
alan.arentsen@database-consultancy.nl

alanarentsen.blogspot.com

www.database-consultancy.nl

Вам также может понравиться