Conditional Buttons and Icons on the SNH Data Table Widget

“Become a beacon of enhancement, and then, when the night is gray, all of the boats will move towards you, bringing their bountiful riches.”
James Altucher

After I posted the SNH Data Table widget collection out on Share, there were a couple of things that I felt were missing in the version that I put out there. One of those was the ability to click on an aggregate column and pull up a list of the records represented by that value. I took care of that one here, but after having second thoughts, the version that I ended up with is not quite like the one described in that installment of the series. Still, after a litter refactoring, I got it working in a way that finally seemed to be acceptable. But there is still one more thing that I would like to add before I release another version of the collection: the ability to control the presence of a button or icon on the row based on some condition.

Right now, if you configure a button or icon, that button or icon appears on every row of the table. That’s a nice feature that the stock Data Table widget does not include, but it would be even nicer if you could control whether or not the button appeared based on some condition. My thought was that I could add yet one more property to the button/icon configuration object called condition that could be used to control the presence of the action item on the row. I wasn’t exactly sure how to make that happen, but as usual, I thought that I would tackle the easiest portion first, which would be to modify the Content Selector Configurator widget to include that additional property. We just went through that exercise when adding the action property to the aggregate column configuration object (which was later replaced with the hint and page_id properties during refactoring), so the exercise is virtually the same.

As we did with the new aggregate column configuration property, we can start with the main widget and add the following to the list of column headings for the buttons and icons section of the table specification:

<th style="text-align: center;">${Condition}</th>

And then in the repeating rows of that table, we can insert this line:

<td data-th="${Condition}">{{btn.condition}}<

On the client side, we can add the following line to the new record section of the editButton() function:

shared.condition = button.condition;

… and this line to the section that saves the edits in that same function:

button.condition = shared.condition || '';

Finally, on the server side, in the Save() function that rebuilds the script, let’s add these lines in the button/icon specification section:

script += "',\n                 condition: '";
script += thisButton.condition;

That will handle things in most cases, but since this particular property is a Javascript expression, we need to account for the fact that the value might contain single quotes, and surrounding a value containing single quotes with single quotes will result in a syntax error in our Script Include. We should at least check for that, and if single quotes are present in the value, we should escape them. Instead of the script fragment above, which has been working for us in all other cases, let’s expand that a little bit to accommodate our concerns to something like this:

script += "',\n					condition: '";
if (thisButton.condition) {
	var condition = thisButton.condition;
	if (condition.indexOf("'") != -1) {
		condition = condition.replace(/'/g, "\\'");
	}
	script += condition;
}

That takes care of the main widget, but we also need to add a new input field to the pop-up editor before this will actually work, so we need to add this line to the HTML of the Button/Icon Editor widget:

<snh-form-field snh-model="c.widget.options.shared.condition" snh-name="condition"/>

That updates the editor to now include a new button/icon specification property called condition. Of course, that doesn’t actually add any functionality to the Data Table widgets just yet, but at least now we can add a value to that property through the editor, which is a start. Now let’s take a look at the actual SNH Data Table widget and see what we need to do in order to leverage that new property.

Once again, the easiest place to start is with the HTML. Here is the current section of the HTML that deals with buttons and icons:

<td ng-repeat="button in data.btnarray" role="cell" class="text-nowrap center" ng-class="{selected: item.selected}" tabindex="0">
  <a ng-if="!button.icon" href="javascript:void(0)" role="button" class="btn-ref btn btn-{{button.color || 'default'}}" ng-click="buttonClick(button.name, item)" title="{{button.hint}}" data-original-title="{{button.hint}}">{{button.label}}</a>
  <a ng-if="button.icon" href="javascript:void(0)" role="button" class="btn-ref btn btn-{{button.color || 'default'}}" ng-click="buttonClick(button.name, item)" title="{{button.hint}}" data-original-title="{{button.hint}}">
    <span class="icon icon-{{button.icon}}" aria-hidden="true"></span>
    <span class="sr-only">{{button.hint}}</span>
  </a>
</td>

In the current version, there are two mutually exclusive anchor tags controlled by ng-if attributes that look to see whether or not an icon image was specified. We should be able to logically and our new condition to the existing conditions without disturbing the rest of the existing structure. The easiest way to do that at this point would simply be to call a function that dealt with the condition and have it return true or false based on the contents of our new condition property. We will have to build that function, but for now, we can just assume that it exists and modify the above to now look like this:

<td ng-repeat="button in data.btnarray" role="cell" class="text-nowrap center" ng-class="{selected: item.selected}" tabindex="0">
  <a ng-if="!button.icon && buttonCondition(button.condition, item)" href="javascript:void(0)" role="button" class="btn-ref btn btn-{{button.color || 'default'}}" ng-click="buttonClick(button.name, item)" title="{{button.hint}}" data-original-title="{{button.hint}}">{{button.label}}</a>
  <a ng-if="button.icon && buttonCondition(button.condition, item)" href="javascript:void(0)" role="button" class="btn-ref btn btn-{{button.color || 'default'}}" ng-click="buttonClick(button.name, item)" title="{{button.hint}}" data-original-title="{{button.hint}}">
    <span class="icon icon-{{button.icon}}" aria-hidden="true"></span>
    <span class="sr-only">{{button.hint}}</span>
  </a>
</td>

That should take care of the HTML. Now we need to come up with a function that will do what we want to do, which is to return true if we want the button/icon to appear and false if we do not. We can start out with something like this:

$scope.buttonCondition = function(expression, item) {
	var response = true;
	if (expression) {
		// check to see if the condition is true or false
	}
	return response;
};

This defaults the response to true, and if there is no condition specified, then the response will be true. If there is a condition, then we need to see if that condition is true for this item. Basically, we want to run the code that is stored in the property value. For that, we can use $scope.$eval. This AngularJS function will run the expression and return the result, which will then become our response. That will make our function look like this:

$scope.buttonCondition = function(expression, item) {
	var response = true;
	if (expression) {
		response = $scope.$eval(expression, this);
	}
	return response;
};

And that should be that! Now all we need to do is test all of this out, plus do a whole lot of regression testing for all of the refactoring, and then we can finally put out a new Update Set. That is definitely quite a bit of work in an of itself, so let’s save all of that for a future installment.

3 thoughts on “Conditional Buttons and Icons on the SNH Data Table Widget”

  • Conan Lloyd says:

    Hello there and thanks again for all this hard work. I finally have my “Subscribe to Announcements” widget working in 2.0 with 2 minor issues. The first is that no matter what I do, the title keeps reverting to the Table instead of the Title I entered. When I refresh the page I can see the widget starts with the Announcements title, but when the table is populated it Changes to Knowledge.

    Secondly, When I loaded and committed 2.1, the buttons on the widget stopped working so I had to revert to 2.0.

    Sorry to bug you with this and I’d be happy to send screen shots if they would help

    • Thanks again for the feedback. I have noticed that title issue myself, but never really looked into. Let me know which of the wrapper widgets you are using to help narrow down my search … thanks for reporting these. It always helps out when other people test things. Oh, and when you say that the buttons are not working, what is the symptom, exactly? Do they not appear or do they not function, and are you launching a new page or listening for the clicks in a companion widget and taking some other action?

    • I had a couple of thoughts on the issues that you reported. On the buttons issue, if the buttons are appearing and nothing is happening when you click on them and you are using a companion widget to listen for the event, it may simply be that you are listening for the event name used in the earlier versions. During the refactoring for v2.1, I standardized all of the various event names, so take a look at some of the sample companion widgets bundled with 2.1 and make sure that you are listening for event names that are being broadcast, and not the names used in the earlier versions.

      As for the title issue, I believe that this is also unique to the earlier versions, and if you can make things work with the latest version, that issue should go away (be sure to check the Use Instance Title option on the widget’s options list). If you can make things work with v2.1, you should really use that one, as it is much improved over the earlier releases. If it turns out that you are just listening for the old event names, then updating your companion widget should fix that problem.

      Also, once you get everything to your liking, it would probably be beneficial to others if you would post a comment or blog post out on the Community Site with some screen shots and any helpful hints that might make things a little easier for the next person who has a similar need. It’s always nice for people who are not the author of the feature to post their experiences and what they had to go through to make things work for their particular use case. It would obviously be interesting to me to see what you were able to do with it, but I think it would be more interesting to other people who might be thinking about trying things out for themselves.

      And thanks again for reporting these issues. Quality feedback always helps make things better.

Comments are closed.