Espresso Grid

Espresso Grid is an editable HTML grid for tables and resources created by an Espresso Logic API. To use it, you simply include espresso-grid.js, create an iframe element in your markup (ex: <iframe id="uniqueID" src="https://eval.espressologic.com/grid"></iframe>), and pass a few initializing parameters, and you're off and running. Once the grid is up, most user interactions taking place within the iframe are broadcast to the container, and depending on the event, the container can alter, update, or even halt an activity. With a few listeners and some lines of code, customizing your grid to look, feel, and behave as expected will seem effortless.

Getting Started

Deploying a simple grid only takes 3 lines of markup:
<script src="https://eval.espressologic.com/grid/espresso-grid.min.js"></script>
<script>var grid = espressoGrid.init({id: 'uniqueID'});</script> <!-- << demo config object -->
<iframe id="uniqueID" src="https://eval.espressologic.com/grid"></iframe>
With this demo config object, we are loading a customers grid from the Espresso Demo sample database. This is a read-only account -- if you have not already registered for an evaluation account, we invite you to do so here -- that way you will be able to follow along with your own project URL's.

Now, assuming we have a running project, which we do in the form of Espresso Demo, we will actually want to pass an authentication object pointed to our own account, so our initializing the grid will now look like:
var grid = espressoGrid.init({
  id: 'uniqueID',
auth: { username: 'demo', password: 'Password1', apiBase: 'https://eval.espressologic.com/rest/livedemo/demo/v1', //<< the Demo project url, change it to reference your project endpoint: 'customer' //<< the database table or custom resource the grid outputs } });
After passing in authentication for your own project (potentially pointed at your own schema), the data in your grid will hopefully look a lot more familiar. With our basic grid output, we can now inspect the configuration object more closely.

Advanced Configuration
Each grid (wrapped in an iframe) waits for the container to broadcast settings spelling out its behavior. This is done in when calling espressoGrid.init(configObj), and while most settings have a default value, we have attempted to make each grid as flexible as possible. It is possible to pass in custom styles and javascript, for instance, or to define exactly what controls should output within the iframe, and others which the container will handle.

The complete configuration object looks a little more complicated than the getting started example, but these settings are rather intuitive.
var configObj = {
	id: 'uniqueID',
	auth: {
		username: 'demo',
		password: 'Password1',
		apiBase: 'https://eval.espressologic.com/rest/livedemo/demo/v1',
		endpoint: 'customer'
	},
	columns: [{field:'name', displayName:'Name'}],
	controls: {
		undo: true,
		search: true,
		fetch: true,
		insert: true,
		save: true,
		del: true
	},
	controlBox: 'bottom',
	parentControls: {
            search: true,
            fetch: true,
        },
	//css: { cssFileHandle: 'https://website.com/styles.css' },
	//js: { jsFileHandle: 'https://website.com/scripts.js' }
};

var grid = espressoGrid.init(configObj);
For this configObj, it may be obvious based on the Getting Started section, "id" and "auth" refer to the html id of the iframe and the authentication parameters for a Logic Designer project respectively. The other attributes are new
  • configObj.columns expects an array of column objects exactly like that passed into the options.columnDefs ng-grid object. It is possible to pass in custom cell templates, and or any other column definition parameter ng-grid would otherwise accept.
  • config.controls allows customization for which controls appear in the iframe
  • config.controlBox expects a string either "top" or "bottom"
  • config.parentControls allows for the same type of customization of button output as config.controls, but in the parent lookup modal
  • config.css expects an object with attributes referencing custom css files to be loaded within the iframe
  • config.js expects an object with attributes referencing custom javascript files to be loaded within the iframe
Event Handling
Many events in the iframe are broadcast to the container through their javascript window properties. Espresso Grid attempts to keep the container as informed as possible, and will also accept instructions for a essentially all manipulations to the grid. For example, in the container, listening for row selections in a grid just requires registering a listener:
//listening
var grid = espressoGrid.init(configObj);
grid.on('EventRowSelected', function (event, row) { console.log(row); });
Broadcasting a row selection is as simple, provided we already have a row object in the grid:
//broadcasting
var grid = espressoGrid.init(configObj);
grid.broadcast('ControlSelectRow', row);
Requesting a summary of the state of the grid is narrowly more complicated, because we first have to broadcast our request, and then listen for the reply:
//pinging
var grid = espressoGrid.init(configObj);

//GetFrameState is a special type of event, it triggers a broadcast back to CustomReplyEvent with information
grid.broadcast('GetFrameState', 'CustomReplyEvent');

grid.on('CustomReplyEvent', function (event, state) {
    console.log(state.table); //detailed table information from an Espresso Logic API /@tables request
});
Using the window.postMessage() method wrapped by espressoGrid, it should be possible to seamlessly manipulate an iframe grid from the container. The events we have explicitly exposed by default are listed below, but additional events can be added by passing in a custom script and taking advantage of the Espresso Transit library.

Events
 Event Name Broadcaster DescriptionExample of Container Use
 GridReadygridA container update indicating the initial state of the grid grid.on('GridReady', function (event, gridState) { var tableColumns = gridState.table.columns; });
 CheckBeforeSearchgridA ping to the container for permission to search grid.reply('CheckBeforeSearch', function (event, filters) { return true; });
 EventAfterSearchgridA ping to the container after a search completes, accepting a return set grid.reply('EventAfterSearch', function (event, data) { console.log(data.newRows); return data.newRows.slice(0, 5); });
 EventBeforeSelectiongridContainer update before a new selection grid.on('EventBeforeSelection', function(event, newRow) { console.log(newRow); });
 EventRowSelectedgridContainer update after a new selection grid.on('EventRowSelected', function (event, selectedRow) { gridSelected.push(selectedRow); });
 EventRowDeselectedgridContainer update after a selected row is de-selected grid.on('EventRowSelected', function (event, deselectedRow) { gridSelected.indexOf(deselectedRow); });
 EventRowInsertedgridContainer update after a row insert grid.on('EventRowInserted', function (event, newRow) { console.log(newRow); });
 CheckStartEditgridA ping to the container for permission to edit a row grid.reply('CheckStartEdit', function (event, row) { return false; }); /* prevents editing rows from the user interface */
 EventRowEditgridContainer update after a cell is blurred grid.on('EventRowEdit', function (event, data) { console.log(data.isSelected); });
 CheckAddRowgridA ping to the container for permission to insert a row grid.reply('CheckAddRow', function (event) { return true; });
 CheckParentLookupgridA ping to the container for permission to do a look up on a parent table grid.reply('CheckParentLookup', function (event) { return true; });
 EventColumnsRefreshedgridContainer update after any change to column definitions grid.on('EventColumnsRefreshed', function (event, colDefs) { var visibleColumns = colDefs; });
 ControlColumnDefinitionsgridA post init broadcast from the container to grid with new column definitions grid.broadcast('ControlColumnDefinitions', colDefs);
 ControlParentLookupSelectioncontainerA container message potentially passing a parent row for selection grid.reply('ControlParentLookupSelection', function (event, userSelectedParentRow) { return otherParentRow; });
 ControlSavecontainerA container message saving any current grid updates or inserts grid.broadcast('ControlSave'); //simple broadcast, no parameters
 ControlDelcontainerA container message deleting any selected & unedited rows grid.broadcast('ControlDel'); //simple broadcast, no parameters
 ControlFetchcontainerA container message requesting another page of grid rows grid.broadcast('ControlFetch'); //simple broadcast, no parameters
 ControlSelectRowcontainerA container message selecting an unselected row grid.broadcast('ControlSelectRow', rowInGrid);
 ControlDeselectRowcontainerA container message deselecting a selected row grid.broadcast('ControlDeselectRow', rowInGrid);
 ControlRunSearchcontainerA container message passing search filters and triggering a search request grid.broadcast('ControlRunSearch', searchFilterArray);
 ControlUpdateRowcontainerA container message updating a grid row grid.broadcast('ControlUpdateRow', { index: rowIndex, row: updatedRowObject });
 ControlInsertRowcontainerA container message inserting a row object into the grid grid.broadcast('ControlInsertRow', newRowObject);
 ControlRawCSScontainerRaw styles passed from the container grid.broadcast('ControlRawCSS', '.grid{ background: #999; }'); 
 GetFrameStatecontainerA container ping for table info and search operators grid.broadcast('GetFrameState', customEventName);
 grid.on(customEventName, function (event, frameState) { console.log(frameState.table, frameState.operators); });
 GetAllRowscontainerA container ping for all rows in the grid grid.broadcast('GetAllRows', customEventName);
 grid.on(customEventName, function (event, allRows) { var gridData = allRows; });
 GetFilterscontainerA container ping for the current search filters grid.broadcast('GetFilters', customEventName);
 grid.on(customEventName, function (event, currentFilters) { var gridSearch = currentFilters });



Subpages (2): Grid Demo Grid Styling
Comments