Friday, February 1, 2013

Metawidget and REST

When using one of the new, pure JavaScript Metawidgets you can use an InspectionResultProcessor to retrieve metadata using Representational State Transfer (REST). Note this is distinct from simply retrieving data using REST. Retreiving data is usually much simpler, as it is done outside of Metawidget.

REST is best performed asychronously. Because of this, we need a way to temporarily suspend Metawidget's inspection process then resume it once the REST call has returned. Inspectors are not suitable for this, because they are designed to operate without any dependency on the UI. This is so they can be deployed on remote tiers of an application (such as the database tier). InspectionResultProcessors, on the other hand, are for those boundary cases where you need both an inspection and access to the UI. REST is one such boundary case.

To create a RestInspectionResultProcessor for your pure JavaScript application, use the following approach:

var mw = new metawidget.Metawidget( document.getElementById( 'metawidget' ), {

   inspectionResultProcessors: [ function( inspectionResult, mw, toInspect, type, names ) {

      var xhr = new XMLHttpRequest();
      xhr.open( "GET", "rest/metadata/get", true );

      xhr.onreadystatechange = function () {
         if ( xhr.readyState == 4 && xhr.status == 200 ) {

            metawidget.util.combineInspectionResults( inspectionResult, JSON.parse( xhr.responseText ));

            // Resume Metawidget operation

            mw.buildWidgets( inspectionResult );
         }
      }

      xhr.send();

      // Return nothing to suspend Metawidget operation
   } ]
} );

For JQuery UI, the code is slightly easier:

$( "#metawidget" ).metawidget( {

   inspectionResultProcessors: [ function( inspectionResult, mw, toInspect, type, names ) {

      $.ajax( 'rest/metadata/get' ).done( function ( data ) {

         metawidget.util.combineInspectionResults( inspectionResult, JSON.parse( data ));

         // Resume Metawidget operation

         mw._refresh( inspectionResult );
      } );

      // Return nothing to suspend Metawidget operation
   } ]
} );

For Angular JS, the code is very similar:

$scope.metawidgetConfig = {

   inspectionResultProcessors: [ function( inspectionResult, mw, toInspect, type, names ) {

      $http.get( 'rest/metadata/get' ).then( function( result ) {

         metawidget.util.combineInspectionResults( inspectionResult, result.data );

         // Resume Metawidget operation

         mw.buildWidgets( inspectionResult );
      } );

      // Return nothing to suspend Metawidget operation
   } ]
};

Working examples of all three approaches can be found in the Metawidget integration tests.

0 comments: