Customizing the Data Table Widget, Part IV

“All life is an experiment. The more experiments you make, the better.”
Ralph Waldo Emerson

Now that we’ve tweaked the Data Table widget to support reference links and action buttons and icons, it’s time to add the code that will process the clicks on the buttons and icons. There are a number of things that we could do here, but since I like to start out small and build things up over time, today I think I will just handle a couple of the options: 1) navigating to another page, and 2) broadcasting the click and letting some other widget or function take it from there. The first is basically just a copy of what is already being done for the primary row link and the reference links and the second is just the weasel way out of building other options into the Data Table widget itself. By broadcasting the details of the click, users can pretty much do whatever it is that they would like to do by setting up listeners for the broadcast, and then I won’t have to add any additional logic or options on my end.

But before we get into all of that, I do have to admit that I got a little sidetracked the other day and started to tinker. Since I had already opened up the code and was messing with it anyway, I decided to go ahead and see if I could add a user avatar to any reference to the sys_user table. I had to dig around a little bit to see how that was done, but it is actually pretty simple with the sn-avatar tag.

Custom Data Table with User Avatars and Presence

I had to play around with the classes for various things to get everything to come out visually the way that I wanted, but the end result turned out to be a relatively simple addition to the HTML:

<td ng-repeat="field in ::data.fields_array" ng-if="!$first" aria-label="{{item[field].display_value}}" ng-class="{selected: item.selected}" data-field="{{::field}}" data-th="{{::data.column_labels[field]}}">
  <sn-avatar ng-if="item[field].value && item[field].type == 'reference' && item[field].table == 'sys_user'"  primary="item[field].value" class="avatar-small" show-presence="true" enable-context-menu="false"></sn-avatar>
  <a ng-if="item[field].value && item[field].type == 'reference'" href="javascript:void(0)" ng-click="go(item[field].table, {sys_id: item[field].value, name: item[field].display_value})" title="${Click for more on }{{::item[field].display_value}}">{{::item[field].display_value}}</a>
  <span ng-if="!item[field].value || item[field].type != 'reference'">{{::item[field].display_value}}</span>
</td>

Now, back to our regularly scheduled programming …

In the main Data Table widget’s Client Controller, I virtually copied the existing go function and then just added in a quick loop to hunt through the configured buttons to find the one that was clicked so that we could pass it on. Other than that, it’s virtually the same as the original:

$scope.buttonclick = function(button, item) {
	spNavStateManager.onRecordChange(c.data.table).then(function() {
		var parms = {};
		parms.table = c.data.table;
		parms.sys_id = item.sys_id;
		parms.record = item;
		for (var b in c.data.buttons) {
			if (c.data.buttons[b].name == button) {
				parms.button = c.data.buttons[b];
			}
		}
		$scope.ignoreLocationChange = true;
		for (var x in c.data.list) {
			c.data.list[x].selected = false;
		}
		item.selected = true;
		$scope.$emit(eventNames.buttonClick, parms);
	}, function() {
		// do nothing in case of closing the modal by clicking on x
	});	
};

Then, on the wrapper widgets, I copied the original listener and hacked it up to look into the button spec to see if there was a page configured. If so, then I navigate to the page; otherwise, I simply broadcast the click on the root scope so that another, independent widget can pick things up from there:

$scope.$on('data_table.buttonClick', callButtonClick);
	
function callButtonClick(e, parms) {
	if (parms.button.page_id) {
		var oid = $location.search().id;
		var p = parms.button.page_id;
		var s = {id: p, table: parms.table, sys_id: parms.sys_id, view: $scope.data.view};
		var newURL = $location.search(s);
		spAriaFocusManager.navigateToLink(newURL.url());
	} else {
		$rootScope.$broadcast('button.click', parms);
	}
}

That was all there was to it. Now all that’s left is to write a sample independent widget to listen for the broadcast and test all of this out to make sure that it all works. That should wrap all of this up quite nicely and should turn out to be the final installment in this particular series.