Dashboards usual comprise several panels which needs to pay attention to each other. For example, a Debt dashboard may contain:
These panels should communicate with each other through event binding. For example:
To wire all this binding, the ObjectBind behavior (in qbo.ObjectBind.js) uses the following patterns: // In Debt.Home.xslt // Add a 'listen' array to the User panel with one event to listen for: 'Reassign' <div id="User" data-behavior="ObjectBind" data-objectbind-options="{ 'class': 'qbo3.DebtObject', 'method': 'Dashboard', 'listen': ['reassign'], 'data': {...} }">.</div> // Add a listen array to the Search panel with one event to listen for: 'Search' <div id="Search" data-behavior="ObjectBind" data-objectbind-options="{ 'class': 'qbo3.DebtObject', 'listen': ['search'] }">.</div> // In Debt.Summary.xslt (used by the User panel) // Note that the event is raised on the qbo3.behavior, which all behaviors are bound to. <a onclick="qbo3.behavior.fireEvent('search', ['Search', { User: '12', 'Title': 'Debts Assigned to {Dimension}' }]);">... </a> The heavy lifting for these methods happens in qbo.ObjectBind.js and qbo3.js: // qbo.ObjectBind.js // Objects can listed for events that cause invokcation or refresh. // E.g.: on Debt Home, a Debt search panel listens for a 'DebtSearch' event // E.g.: on Person Home, a Role Summary listens for 'SystemRoleEdit', to refresh itself whenever roles are edited. if (options.listen) { options.listen.each(function (l) { api.addEvent(l, function (method, data) { if ((method == null) && data) qboObject.refresh(data, true); else if (method && data) qboObject.invokeHtml(method, data); else if (typeOf(method) == "object") qboObject.refresh(method, true); else qboObject.refresh(); }); }); } // qbo3.js' qbo3.AbstractObject // in invoke*'s onSuccess handler ... this.fireEvent('success', method); ... In the example above, we have a hyperlink click handler fire an event to cause a search to happen. In some use cases, we may wish to change the results in a dashboard and in a search panel at the same time. For example, we may allow the user to 'filter' results to 'Active' or 'Delinquent'. Any statement that includes {Where.Filters} can use a generic parameter called 'SqlFilters' to limit results. For example:
In this case, we essentially want to append {SqlFilters:'Active'} to both the Dashboard and Search panels simultaneously. To achieve this, we can have both panels listen for a global filter event called 'filterDebt'. When the following javascript is fired, both panels with refresh with the appropriate filter applied: qbo3.behavior.fireEvent('filterDebt', {SqlFilters: 'Delinquent'}); Note in this example, there is only one parameter passed to fireEvent. The ObjectBind behavior is smart enough to call 'refresh' if you don't specify a method and data. In fact, this pattern is common enough that ObjectBind automatically wires each object to listen for a 'filter{Object}' event raised anywhere in the qbo3.behavior. Thus, the following markup work the same way: <div id="Search" data-behavior="ObjectBind" data-objectbind-options="{ 'class': 'qbo3.DebtObject', 'listen': ['search', 'filterDebt'] }">.</div>
<div id="Search" data-behavior="ObjectBind" data-objectbind-options="{ 'class': 'qbo3.DebtObject', 'listen': ['search'] }">.</div> Caching Data on the BrowserHTML5 supports extended storage capabilities via sessionStorage and localStorage. QBO3 leverages HTML5 storage to speed draw times of containers, and to lighten the load on the server. This functionality is implemented by default for all qbo3.AbstractObject-derived classes.
For example:
<span class="rendertime"></span> tag, the cached date and time will be displayed until the data is refreshed from the server.<div data-behavior="ObjectBind" data-objectbind-options="{{ remember: false }}">.</div> <div data-behavior="ObjectBind" data-objectbind-options="{{ cacheKey: 'MyWorklist.Summary' }}">.</div> Implementation follows:
Relevant methods include: From qbo3: // Clears storage of any keys beginning with path; if path is null, document.location.pathname is used. clearStorage: function (path) { ... } From qbo3.AbstractObject: // Gets a storage key for use by sessionStorage cacheKey: function (method) { return this.options.cacheKey || document.location.pathname + this.options.target.id + (method || this.method); } // Reads content from HTML5 storage, if available readStorage: function (method) { ... } // Writes content to HTML5 storage, if available writeStorage: function (html, script) { ... } // Clears content from HTML5 storage, if available clearStorage: function (method) { ... } From qbo.ObjectBind.js: // Load data from storage if allowed, otherwise fetch from the server. if (!qboObject.options.remember || !qboObject.readStorage(method)) qboObject.invokeHtml(method, data); |
Quandis Business Objects 3 > QBO 3 Blog >