WebORB Presentation Server
Rich Client Primer - AJAX Client

Phone Book Example

Create New Contact
Name
Phone Number
Email Address


Phone Book
Instructions:
Enter data in the fields on the left and click 'Create Contact'. When you click the button, the data is sent to the server object which updates the database. New contacts are added to the last page. As page reaches 10 contacts, new page is added.

Each contact can be edited using the Edit button or deleted using the Delete buttons. All actions immediately update the database.

Notes:
This example demonstrates the usage of the data binding API available in Rich Client System. Specifically it explores the following capabilities:
- Database records retrieval
- Database update using remote method invocation
- Database paging

Implementation:
When the page loads, it performs a binding call to get a proxy to a server-side object. The object implements
the logic of retrieving, updating or deleting data in the database. The client code maintains in its state the page a user is on and reuses the proxy object for subsequent invocations to show a page, add, update or delete a contact.

Code review

The client imports the Rich Client System's™ JavaScript library:

<script language="javascript" src="WebORB.js"></script>

As soon browser loads the page, it executes the function where initial object binding takes place:

<body onLoad="loadPhoneBook();">

The loadPhoneBook() function binds to a server side object and performs asynchronous remote method invocation to load the contacts. The Async object in the arguments list of getAllContacts() causes the method to be invoked asynchronously. When the response becomes available, Rich Client System invokes the processContacts method.

proxy = webORB.bind(
      "weborb.examples.primer.PhoneBook",    
      "http://www.themidnightcoders.com/examples/weborb.aspx"+
      "?activate=application" );
proxy.getAllContacts( new Async( processContacts ) );

The client-server interaction for the first invocation consists of the following steps:

(1). Client invokes the getAllContacts() method on a remote object via WebORB server, WebORB
       server dispatches the invocation to the phonebook object (
weborb.examples.primer.PhoneBook)
(2). The object executes a database query and returns a data set
(3). WebORB caches the result for subsequent paging requests and serializes the first page back to
       the client
(4). Rich Client System processes the response and invokes the processContacts function.
      The function was specified in the Async object passed to the original invocation. The
       processContacts function contains the logic for rendering the data in the browser.

Rendering columns

Whenever a server object returns a dataset, Rich Client System presents the response as a RecordSet object. RecordSet contains several functions providing information about the dataset. One of the functions is getColumnNames. The use of it is demonstrated below:
 

// contacts is a RecordSet object. It contains a response
// from the getAllContacts invocation.

var columnNames = contacts.getColumnNames();

for( var i = 0; i < columnNames.length; i++ )
{
  var colNameCell = document.createElement( "TD" );
  colNameCell.style.backgroundColor = "#C0C0C0";
  colNameCell.style.color = "#000000";
  var colName = columnNames[ i ];

  if( colName == "ID" )
    colName = "";

  colNameCell.innerHTML = "<font size='2'>" + colName + "</font>";
  headerRowObj.appendChild( colNameCell );
}

Creating client-side pager

WebORB automatically supports paging (which can be turned off if needed). If WebORB serializes query responses in a paged format, the client may choose provide paging capability as shown in this example:
 

// contacts is a RecordSet object. It contains a response
// from the getAllContacts invocation.


var totalRows = contacts.getTotalRowCount();
var pageSize = contacts.getPageSize();
var pageCount = 1;

// if there are any rows in the response, create pager
while( totalRows > 0 )
{
  // create a hyperlink for every page
  var linkElement = document.createElement( "A" );
  linkElement.innerHTML = "<font size='2'>" + pageCount + "</font>";

  // create a dynamic function which will fetch
  // data for the selected page
  linkElement.onclick = function()
  {
    // invoke remote method when a user clicks on the page number
    // getRecords is a special function on the RecordSet object
    // this method is invoked synchronously, just for the sake of
    // demonstration. Production quality application should use the
    // asynchronous version of the call

    var result = contacts.getRecords(
             (arguments.callee.pageCount - 1) * pageSize + 1, pageSize );

    // once a response is available, render its data
    renderContacts( result.Page, arguments.callee.owner );
    // adjust current page number
    curPage = arguments.callee.pageCount;
  }
  // store the data on the function reference.
  // The data is used in the onclick handler above

  linkElement.onclick.pageCount = pageCount;
  linkElement.onclick.owner = linkElement;

  linkElement.href = "javascript:";
  // increment page count and move on to rendering the
  // next page number, if one is available

  pageCount++;
  totalRows -= pageSize;

  pager.appendChild( linkElement );
  pager.appendChild( document.createTextNode( " " ) );
}

Copyright © Midnight Coders, LLC, 2005. All Rights Reserved