How can we build a widget that ingests or displays content from our digital workplace? We can do this quite easily with ‘
Axios’, which we’ve built into the platform.
What’s Axios?
Axios is a powerful promise based HTTP client available for your browser and node.js. It allows you to easily make API calls to content or data endpoints in your digital workplace without having to worry about re-authenticating. Every Igloo digital workplace has Axios available to widgets it out-of-the box.
How can I use it?
In our example, we’ll build a widget that displays the 10 most recent blog posts in a channel.
Let’s dive into some simple code:
<html lang="en"> <head> <meta charset="UTF-8"> <title>Top Blog Posts Widget</title> <script type="text/JavaScript" src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script> <style></style> </head> <body> <div id="posts"></div> <script> // this handy function gets the configuration items from the widget config function createConfiguration () { if (window.frameElement.getWidgetConfig) { const config = window.frameElement.getWidgetConfig() window.widgetConfig = {} if (confif) { for (const key in config) { if (Object.prototype.hasOwnProperty.call(config, key)) { window.widgetConfig[key] = config[key].toString() } } } } return window.widgetConfig } // get the configuration const config = createConfiguration() // build the url. We're going to 'get children by path' The path is passed to us from the config const url = `.api/api.svc/objects/byPath/children/view?path=${config.path}&maxcount=${config.count}&startindex=0&orderby=PublishedDateDesc&includefuturepublished=false` parent.axios.get(url) .then((response) => { let blogPostTable = '<table><tr><th>Title</th><th>Description</th><th>Date</th></tr>' const blogs = response.data.response.items // loop through the items in the response data and populate our table blogs.forEach((blogItem) => { // we'll use the 'moment' lib to parse the date string from the response data and format it. const createdDate = moment(blogItem.created.date, 'x').format('MMM Do \'YY, h:mm a') blogPostTable += `<tr><td><a href=${ // href links back to teh original document. We'll target the _parent blogItem.href} target=_parent${ blogItem.title}</a></td><td>${ blogItem.articleSummary}</td><td>${ createdDate}</td></tr>` }) </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.0.4/iframeResizer.contentWindow.js"></script> </body> </html>
We’ll focus on lines 50 through 57 where we’re making a call into the digital workplace using Axios. To access the blog posts on a channel we’ll use the endpoint /.api/api.svc/objects/byPath/children/view
We start by populating the endpoint URL with content from our configuration. In this case, the object’s path (config.path), and the number of items to return (config.count). Since axios is available to every widget you can call it through the parent within your <script> tag.
This endpoint takes the following query parameters:
- path - This will depend on your workplace
- maxcount - The number of records to return
- startindex - The starting record. This is handy to create a widget that pages through the results.
- orderby - The sort order of items to be returned. We’re going to use “PublishedDateDesc” – which means we’re going to return results from most to least recently published.
- includefuturepublished - controls whether the retunedresults include content set to be published in the future. We have this set to ‘false’ in our example.
In the response we’re going to look at data->response->items[]. We’ll iterate through this array and build a table with the results:
const url = `.api/api.svc/objects/byPath/children/view?path=${config.path}&maxcount=${ config.count}&startindex=0&orderby=PublishedDateDesc&includefuturepublished=false` parent.axios.get(url) .then((response) => { let blogPostTable = '<table><tr><th>Title</th><th>Description</th><th>Date</th></tr>' const blogs = response.data.response. items // loop through the items in the response data and populate our table blogs.forEach((blogItem) => { // we'll use the 'moment' lib to parse the date string from the response data and format it. const createdDate = moment(blogItem.created.date, 'x').format('MMM Do \'YY, h:mm a') blogPostTable += `<tr><td><a href=${ // href links back to the original document. We'll target the parent. blogItem.href} target=_parent>${ blogItem.title}</a></td><td>${ blogItem.articleSummary}</td>td>${ createdDate}</td></tr>` }) // and finally, let's not forget the </> tag for the table. blogpostTable += '</table> document.getElementById('posts').innerHTML = blogPostTable }) .catch((error) => { // we really should handle errors... better than this... const errorMessage = `<div class='error'>Whoops!<br>${error}</div>` document.getElementById('posts').innerHTML = errorMessage })
The complete call is shown above. We’re iterating through the ‘response.data.response.items’ array and populating our table with the content. Some basic error handing has also been added to assist with troubleshooting.
The Result
Here’s how the widget looks:
To Dos
This simple widget was created to illustrate how easy it is to access your Igloo digital workplace content from within a widget. However, it’s far from complete. Next steps would include:
- Type checking should be implemented. By examining the __type parameter for each item, you can validate that you’re looking at the object you’re expecting.
- Better error handling. The example here spits out the error code in an alert <div>. A proper widget should catch all relevant error codes and provide friendly messaging to your end-users.
Our article What makes a widget great! also provides ideas for improving your widgets.
Caveats
It should be noted that Igloo’s ‘view’ APIs (including the one we’ve used) will count as a page view. Your digital workplace’s analytics will reflect this.
0 Comments