Configurable Data Table Widget Content Selector, Corrected

“No great thing is created suddenly.”
Epictetus

While playing around with my new Content Selector Configuration Editor, I ran into a few errors in my Configurable Data Table Widget Content Selector when working in the Portal Page Designer. The problem that I ran into was that errors in widget prevented the widget from appearing in the container, which then prevented you from accessing the widget controls that let you edit the widget options or delete the widget. I had run into something similar before with my Dynamic Service Portal Breadcrumbs, so I pretty much knew what was going on — I just needed to hunt down the specific error. In this particular case, it turned out to me more than one error, and fixing the first one still did not solve the problem completely.

The problem occurs when first dragging the widget onto a page. Before you have an opportunity to edit the widget options and specify a configuration script,the widget tries to run without a configuration script and then it crashes because it has no configuration script. Here is the offending code:

if (!c.data.table) {
	if (c.data.config.defaults.table) {
		refreshPage(c.data.config.defaults.table, c.data.config.defaults.perspective, c.data.config.defaults.state);
	} else {
		window.location.search = '';
	}
}

The problem is that second line that wants to grab the default table value from the defaults object in the configuration. Since we haven’t had a chance to specify a configuration script just yet, there is no defaults object in the configuration, and attempting to access the table property of that nonexistent object will earn you a NullPointerException. That’s not good! Before checking for the table property, we need to first check to see if the defaults object exists. This modification should do the trick:

if (!c.data.table) {
	if (c.data.config.defaults && c.data.config.defaults.table) {
		refreshPage(c.data.config.defaults.table, c.data.config.defaults.perspective, c.data.config.defaults.state);
	} else {
		$location.search('');
	}
}

That keeps the widget from crashing, but there is still no content displayed on the screen in the Page Designer, so I decided to add a little something to the top of the HTML that would only show if there was no configuration script specified. That code looks like this:

<div ng-hide="options && options.configuration_script">
  <div class="alert alert-danger">
    ${You must specify a configuration script using the widget option editor}
  </div>
</div>

Now when you drag a brand new copy of the widget onto the canvas in the Page Designer, you get this:

Content Selector widget with no configuration script specified

That takes care of an empty configuration script name, but what if you enter a name for script that isn’t a valid Script Include? Well, that crashes the widget code as well, so we will need to fix that, too. This time, the issue is on the server side, where we were assuming that we would always get an instance of whatever script was specified. As you can see from the following code snippet, we don’t even bother to check to see if something was returned from the Instantiator:

var configurator = instantiator.getInstance(options.configuration_script);
data.config = configurator.getConfig($sp);
data.config.authorizedPerspective = getAuthorizedPerspectives();
establsihDefaults();

That’s another easy fix, though. We just need to check to make sure that it is there before we attempt to use it.

var configurator = instantiator.getInstance(options.configuration_script);
if (configurator != null) {
	data.config = configurator.getConfig($sp);
	data.config.authorizedPerspective = getAuthorizedPerspectives();
	establishDefaults();
}

Here is another instance where it would be good to let the developer know that something is amiss, so I added yet anothe DIV to the top of the HTML:

<div ng-show="options && options.configuration_script && !data.config.defaults">
  <div class="alert alert-danger">
    {{options.configuration_script}} ${is not a valid Script Include}
  </div>
</div>

Here’s how that looks in action:

Error message when a invalid Script Include is specified

That should resolve all of the errors that I have discovered so far. Here is the corrected Update Set, which should replace all of the broken parts in the last one and get things working again.