Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Battle of the tools

No description
by

Dick Dral

on 30 April 2017

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of Battle of the tools

Battle of the tools
Apex vs. Oracle JET
What is Smart4apex?
Dick Dral
Whoat is Smart4apex?
www.smart4apex.nl
Dick Dral
2005
2010
now
1980
2015
(one of the) first Oracle customer(s) in Europe

Sharing code
Presentations
Independent Contractor
E-mail:
Linkedin:
Twitter:
Blog:
Websites:
dick.dral@detora.nl
dickdral
@dickdral
dickdral.blogspot.nl
www.detora.nl
www.speech2form.com
www.speech2form.com/ords/f?p=OPFG
Agenda
<>
Apex
JET
architecture
source
components
Map Component
Apex
JET
<div id='thematicMap' data-bind="ojComponent:{
component: 'ojThematicMap',
basemap: map_name,
areaLayers: layers,
optionChange: mapOptionChange
}"
style="width:100%">
</div>

HTML
JavaScript
self.map_name = ko.observable('world');

ko.computed( function()
{
self.map_name ( get_map_name_for_country(self.country_id()) );
}
, self);

self.layers = ko.observableArray( [{layer: 'countries',
labelDisplay: 'off',
areaDataLayer: {id: 'adl1',
selectionMode: 'single',
areas: get_map_data
(self.country_id(),
self.subject()) }}]);
6 Map Regions
with 4 Series each
CRUD Page
Apex
JET
HTML: 99 lines
JavaScript: 131 lines
/**
* Copyright (c) 2014, 2017, Oracle and/or its affiliates.
* The Universal Permissive License (UPL), Version 1.0
*/
define(['ojs/ojcore', 'knockout', 'ojs/ojmodel', 'MockRESTServer'],
function (oj, ko) {


function viewModel() {
var self = this;
self.serviceURL = 'http://mockrest/stable/rest/Departments';
self.Departments = ko.observableArray([]);
self.DeptCol = ko.observable();
self.datasource = ko.observable();
self.somethingChecked = ko.observable(false);
self.currentDeptName = ko.observable('default');
self.workingId = ko.observable('');

self.fetch = function (successCallBack) {

// populate the collection by calling fetch()
self.DeptCol().fetch({
success: successCallBack,
error: function (jqXHR, textStatus, errorThrown) {
console.log('Error in fetch: ' + textStatus);
}
});
};

function parseDept(response) {
if (response['Departments']) {
var innerResponse = response['Departments'][0];
if (innerResponse.links.Employees == undefined) {
var empHref = '';
} else {
empHref = innerResponse.links.Employees.href;
}
return {DepartmentId: innerResponse['DepartmentId'], DepartmentName: innerResponse['DepartmentName'], links: {Employees: {rel: 'child', href: empHref}}};
}
return {DepartmentId: response['DepartmentId'], DepartmentName: response['DepartmentName'], LocationId:response['LocationId'], ManagerId:response['LocationId'], links: {Employees: {rel: 'child', href: response['links']['Employees'].href}}};
}

function parseSaveDept(response) {
return {DepartmentId: response['DepartmentId'], DepartmentName: response['DepartmentName'], LocationId:response['LocationId'], ManagerId:response['ManagerId'], links: {Employees: {rel: 'child', href: response['links']['Employees'].href}}};
}

self.findDeptIds = function() {
var selectedIdsArray = [];
$("input:checkbox").each(function() {
var cb = $(this);
if (cb.is(":checked")) {
selectedIdsArray.push(cb.attr("id"));
}
});
return selectedIdsArray;
}

// Deletion handlers/helpers
self.enableDelete = function() {
if (!$('input[type=checkbox]:checked').length) {
self.somethingChecked(false);
} else {
self.somethingChecked(true);
}
return true;
}

self.deleteDepartment = function(data, event) {
var deptIds = [];
deptIds = self.findDeptIds();
var collection = data.DeptCol();
deptIds.forEach(function(value, index, arr) {
var model = collection.get(parseInt(value));
if (model) {
collection.remove(model);
model.destroy();
}
});
self.enableDelete();
$('#demoTable').ojTable('refresh');
}

// Update handlers/helpers
self.showChangeNameDialog = function(deptId, data, event) {
var currName = data.DepartmentName;
self.workingId(deptId);
self.currentDeptName(currName);
$('#editDialog').ojDialog('open');
}

self.updateDeptName = function(formData, event) {
var currentId = self.workingId();
var newName = formData.elements[0].value;
if (newName != self.currentDeptName() && newName != '') {
var myCollection = self.DeptCol();
var myModel = myCollection.get(currentId);
myModel.save({'DepartmentName': newName}, {
success: function(myModel, response, options) {
$('#editDialog').ojDialog('close');
},
error: function(jqXHR, textStatus, errorThrown) {
alert("Update failed with: " + textStatus);
$('#editDialog').ojDialog('close');
}
});
} else {
alert('Department Name is not different or the new name is not valid');
$('#editDialog').ojDialog('close');
}
};

// Create handler
self.addDepartment = function (formElement, event) {
var id = $("#newDepartId").val();
var recordAttrs = {DepartmentId: id, DepartmentName: $("#newDepartName").val(),
ManagerId: "", LocationId: "",
links: {Employees: {rel: 'child', href: self.serviceURL + '/' + id + '/Employees'}}};
this.DeptCol().create(recordAttrs, {
'contentType': 'application/vnd.oracle.adf.resource+json',
success: function (response) {
//console.log('Success in Create');
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('Error in Create: ' + textStatus);
}
});
};

// think of this as a single record in the DB, or a single row in your table
var Department = oj.Model.extend({
urlRoot: self.serviceURL,
parse: parseDept,
parseSave: parseSaveDept,
idAttribute: 'DepartmentId'
});

var myDept = new Department();

// this defines our collection and what models it will hold
var DeptCollection = oj.Collection.extend({
url: self.serviceURL + "?limit=50",
model: myDept,
comparator: "DepartmentId"
});

self.DeptCol(new DeptCollection());
self.datasource(new oj.CollectionTableDataSource(self.DeptCol()));
}
return {'deptVM': viewModel};
}
);

1 Interactive Grid Region
<html>
<head>
<title>Oracle JET Common Model - CRUD</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

<!-- This is the main css file for the default Alta theme -->
<link rel="stylesheet" href="css/libs/oj/v2.3.0/alta/oj-alta-min.css" type="text/css"/>

<!-- These style classes are for demonstration purposes only. The JET framework DOES NOT include
a framework level icon set. You can use this example as a basis for defining your own icons. -->
<link rel="stylesheet" href="css/demo-icons.css">

<!-- This is where you would add any app specific styling -->
<link rel="stylesheet" href="css/override.css" type="text/css"/>

<!-- RequireJS bootstrap file -->
<script data-main="js/main" src="js/libs/require/require.js"></script>

</head>
<body>
<div id="globalBody"> <!-- This div helps make sure the footer stays at the bottom of the page -->
<!-- branding -->
<header>
<div id="divBrandBar" class="demo-brand-bar short">
<div class="oj-flex oj-flex-items-pad">
<div id="divHeaderContainer" class="oj-flex-item oj-sm-12 oj-md-12 demo-container demo-brand-container page-padding">
<a id="aBranding" class="demo-branding" href="#">
<img class="demo-logo" alt="Oracle" src="css/images/t.gif"/>
<span id="spanProductName">JET Common Model (CRUD)</span>
</a>
</div>
</div>
</div>
</header>

<!-- This is where your main page content will be loaded -->
<div class="oj-flex oj-flex-items-pad">
<div id="mainContent" class="oj-flex-item oj-sm-12 oj-md-12 demo-page-content-area page-padding" style="display: none;">
<div class="page-padding">
<div id="deptList" class="oj-flex-item oj-md-9 oj-sm-12">
<table id="table"
data-bind="ojComponent: {component: 'ojTable',
data: datasource,
columns: [{headerText: 'Remove', id: 'column1', sortable: 'disabled'},
{headerText: 'Department Id',
field: 'DepartmentId', sortable: 'enabled'},
{headerText: 'Department Name',
field: 'DepartmentName', sortable: 'enabled'},
{headerText: 'Location Id',
field: 'LocationId'},
{headerText: 'Manager Id',
field: 'ManagerId'}],
selectionMode: {row: 'none', column:'none'},
rowTemplate: 'row_tmpl'}">
</table>
<br/>
(Click on a Department Name to edit it)
<br/><br/>
<button id="deleteDept_btn" data-bind="enable: somethingChecked, click: deleteDepartment">Remove Department</button>
<br/>
<div id="editDialog" title="Change Department Name" data-bind="ojComponent:{component: 'ojDialog', initialVisibility: 'hide', resizeBehavior: 'none', dragAffordance: 'title-bar', modality: 'modeless'}">
<form class="oj-form oj-sm-odd-cols-12" data-bind="submit: updateDeptName">

<!-- Example of custom dialog header. Setting the class "oj-dialog-header" will tell the dialog to
use the contents of that <div> as the header content. Leaving this <div> out will cause the default header
to be used, which uses the title attribute as the header content value. -->
<div class="oj-dialog-header oj-helper-clearfix" aria-labelledby="dialog-title-id">
<div>
<span id="infoIcon" class="oj-message-status-icon oj-message-info-icon" style="float:left; margin-right: 10px"></span>
<span id="dialog-title-id" class="oj-dialog-title">Change Department Name</span>
</div>
</div>
<div class="oj-dialog-body">
<div class="oj-md-odd-cols-4">
<label for="newName" class="oj-label oj-label-inline">Department Name</label>
<input id="newName" type="text" data-bind="ojComponent: {component:'ojInputText', value: currentDeptName()}">
</div>
</div>
<div class="oj-dialog-footer">
<button id="submitBtn" type="submit" data-bind="ojComponent: {component:'ojButton', label: 'Change'}"></button>
<button id="resetBtn" data-bind="ojComponent: {component: 'ojButton', label: 'Cancel'}, click: function(){$('#editDialog').ojDialog('close');}"></button>
</div>
</form>
</div>
<br/>
<!-- A simple form is used to add a new department record. -->
<div id="addDept" class="oj-flex-item oj-md-3 oj-sm-12 right">
<div id="quickUpdate" class="frame">
<div id="newDeptForm">
<form class="oj-form oj-sm-odd-cols-12 oj-md-odd-cols-6 oj-md-labels-inline" data-bind="submit: addDepartment">
<h3>New Department</h3><hr/>
<div class="oj-flex">
<div class="oj-flex-item">
<label for="newDepartId" class="oj-label">Department Id</label>
</div>
<div class="oj-flex-item">
<input id="newDepartId" value="555" class="oj-text-input" data-bind="ojComponent:{component:'ojInputNumber'}" />
</div>
</div>
<div class="oj-flex">
<div class="oj-flex-item">
<label for="newDepartName" class="oj-label">Department Name</label>
</div>
<div class="oj-flex-item">
<input id="newDepartName" maxlength='30' placeholder="enter new name" data-bind="ojComponent:{component:'ojInputText'}"/>
<button id="saveBtn" class="oj-button" type="submit" data-bind="ojComponent:{component:'ojButton', label: 'Add Department'}"></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>


8 mouse clicks
enter Page number and title
HTML from DB
HTML from client
generated HTML
some JS and CSS
Apex architecture
Oracle JET Architecture
HTML generated on client
much JS on the client!
only server access for data or services
Cordova
Apex Builder
Files...
Apex Builder
NetBeans IDE
Apex
JET
Apex 5.1 :
JET Charts
Apex Components
JET Components
function mainContentViewModel() {
var self = this;
...
self.country_id = ko.observableArray(["1"]);
window.country_id = self.country_id;

// define source for sunburst chart data ( only for regions )
self.nodevalues = ko.observableArray();
ko.computed( function() {
if ( self.country_id() < 100 )
{ var nodes = get_hierarchy( self.country_id(), self.subject() );
self.nodevalues([nodes]);
}
}, self);

// define action on click in sunburst
ko.computed(function() {
if ( self.sunburstSelectedNode() )
{
self.country_id (country_id_from_name(self.sunburstSelectedNode()).toString() );
self.sunburstSelectedNode('');
}
}, self);
...

Functioning of ViewModel 1 / 2
...
<select id="country" data-bind="ojComponent: {component: 'ojSelect',
value: country_id,
rootAttributes: {style:'max-width:20em'}
}">
<!-- ko foreach: countries -->
<option data-bind="value : value, text: label"></option>
<!-- /ko -->
</select>
...
<div id='sunburst-container' style="width:100%;">
<div data-bind="ojComponent: {
component: 'ojSunburst',
selectionMode: 'single',
selection: sunburstSelectedNode,
...
nodes: nodevalues
}"
style="width:100%; height:100%;">
...
Functioning of ViewModel 2/2
Apex
JET
mobile
CRUD app
speed
lines of code
maintainable
learning
+/-
++
++
++
+/-
++
+
-
+/-
-
+
+/-
dashboard
+
++
Demo Apex World Dashboard
Demo JET World Dashboard
Full transcript