Calling Data Abstract Servers from JavaScript
From RemObjects Wiki
This is an Article about Data Abstract for JavaScript
Feel free to add your notes to this topic below.
New page awaiting review
Please do not rely on the content. After review, the page will be indexed and may have its name changed.
If you have suggestions for this page, please send them to us: email.
Contents |
Server side
Create a Data Abstract server following the Easy Steps to Create a Data Abstract Application (Delphi) or Easy Steps to Create a Data Abstract Application (.NET) articles.
Add TDAJavaScriptHttpDispatcher (Delphi) or DAJavaScriptHttpDispatcher (.NET) component to the server DataModule and connect its Server property to your server channel.
(TODO: add screenshot here)
Compile and run the server.
Client side
Create index.html in the html subfolder of your project folder. Start with
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script src="RemObjectsSDK.js" type="text/javascript"></script> <script src="DataAbstract.js" type="text/javascript"></script> <script src="DataAbstract4_intf.js" type="text/javascript"></script> </head> <body> </body> </html>
What do we need:
- HTTPClientChannel object to perform http communications.
- BinMessage object to serialize data.
- DataAbstractService object to perform service calls.
- RemoteDataAdapter object to hide lowlevel things from us.
- Table object to hold data.
- HtmlTableView object to display table data in a simple read only manner.
var Channel = new RemObjects.SDK.HTTPClientChannel("http://" + window.location.host + "/BIN"); var Message = new RemObjects.SDK.BinMessage(); var Service = new RemObjects.SDK.RemoteService(Channel, Message, "DataService"); var daService = new DataAbstractService(Service); var loginService = new RemObjects.SDK.RemoteService(Channel, Message, "LoginService"); var Adapter = new RemObjects.DataAbstract.RemoteDataAdapter(Service, loginService, RemObjects.DataAbstract.Bin2DataStreamer); Adapter.onLoginNeeded = function (aCallback) { this.login("John", "John", function(msg) { if (aCallback) aCallback(); }, RemObjects.UTIL.showError); } var Table = new RemObjects.DataAbstract.DataTable('customers');
Then we need a placeholder for HtmlTableView and its header style
<table id="myTable"> </table> <style> .da_htmlTableHeader { background-color: aqua; } </style>
Finally, getting the data:
Adapter.getData(Table, RemObjects.DataAbstract.Util.createRequestInfo(true, -1, '', []), function() { new RemObjects.DataAbstract.Views.HtmlTableView(Table, 'myTable'); }, RemObjects.UTIL.showError );
Thats it! Minimal web application retrieving table data from the Data Abstract server is ready.
Full index.html
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <script src="RemObjectsSDK.js" type="text/javascript"></script> <script src="DataAbstract.js" type="text/javascript"></script> <script src="DataAbstract4_intf.js" type="text/javascript"></script> </head> <body> <table id="myTable"> </table> <style> .da_htmlTableHeader { background-color: aqua; } </style> <script> var Channel = new RemObjects.SDK.HTTPClientChannel("http://" + window.location.host + "/BIN"); var Message = new RemObjects.SDK.BinMessage(); var Service = new RemObjects.SDK.RemoteService(Channel, Message, "DataService"); var daService = new DataAbstractService(Service); var loginService = new RemObjects.SDK.RemoteService(Channel, Message, "LoginService"); var Adapter = new RemObjects.DataAbstract.RemoteDataAdapter(Service, loginService, RemObjects.DataAbstract.Bin2DataStreamer); Adapter.onLoginNeeded = function (aCallback) { this.login("John", "John", function(msg) {var workersTable = new RemObjects.DataAbstract.DataTable("workers"); if (aCallback) aCallback(); }, RemObjects.UTIL.showError); } var Table = new RemObjects.DataAbstract.DataTable("customers"); Adapter.getData(Table, RemObjects.DataAbstract.Util.createRequestInfo(true, -1, "", []), function() { new RemObjects.DataAbstract.Views.HtmlTableView(Table, "myTable"); }, RemObjects.UTIL.showError ); </script> </body> </html>
Calling Relativity
Relativity server serves RemObjectsSDK.js, DataAbstract.js and DataAbstract4_intf.js. Also it has cross origin resource sharing (CORS) capability so can be accessed by any html file, even opened from local disk.
So, let's assume that Relativity server is running at http://localhost:7099
In this case we should use absolute paths for scripts and channel.
<script src="http://localhost:7099/js/RemObjectsSDK.js" type="text/javascript"></script> <script src="http://localhost:7099/js/DataAbstract.js" type="text/javascript"></script> <script src="http://localhost:7099/js/DataAbstract4_intf.js" type="text/javascript"></script>
var Channel = new RemObjects.SDK.HTTPClientChannel("http://localhost:7099/JSON/");
Then we need to login before making any data call. RemoteDataAdapter.login takes a callback function as a parameter and calls it when successfully logged in so we could put there getData call from previous example.
Adapter.login("User=Data;Password=Relativity;Domain=PCTrade Sample", function() { Adapter.getData(Table, RemObjects.DataAbstract.Util.createRequestInfo(true, -1, '', []), function() { new RemObjects.DataAbstract.Views.HtmlTableView(Table, 'myTable'); }, RemObjects.UTIL.showError) }, RemObjects.UTIL.ShowError);
Dynamic script loading
What to do if we don't know server address at design time i.e. user enters server address into input field and hits connect button. Important! We need scripts to be loaded synchronously in a right order.
Let's assume that we have on a page
<input id="server-address" type="text"> <input type="submit" value="connect" onclick="loadAll();">
Then wrapping our login-getData call chain into a function retrieveData() and here we are:
function includeScript(scriptSrc, callback) { var headID = document.getElementsByTagName("head")[0]; var newScript = document.createElement('script'); newScript.type = 'text/javascript'; newScript.onload=callback; newScript.src = scriptSrc; headID.appendChild(newScript); } function loadAll() { var baseUrl = "http://" + document.getElementById("server-address").value + "/js/"; includeScript(baseUrl + "RemObjectsSDK.js", function() { includeScript(baseUrl + "DataAbstract.js", function() { includeScript(baseUrl + "DataAbstract4_intf.js", function() { retrieveData(); }); }); }); }
Blobs
Generally blobs are just strings containing binary data. Here's how to display workers photos from PCTrade sample database
var workersTable = new RemObjects.DataAbstract.DataTable("workers"); Adapter.getData(workersTable, RemObjects.DataAbstract.Util.createRequestInfo(true, -1, '', []), function() { workersTable.first(); //of course, there are .next() and .prev() too document.getElementById("photo").src = "data:image/jpeg;base64," + RemObjects.UTIL.toBase64(workersTable.getFieldValue("workerphoto")); //put <img id="photo" src=""> in the page body }, RemObjects.UTIL.showError);
Product: RemObjects Data Abstract
Available Editions: Data Abstract for .NET, Xcode, Delphi, Java and JavaScript