Configurable Data Table Widget Content Selector, Part IV

“It has long been an axiom of mine that the little things are infinitely the most important.”
Sir Arthur Conan Doyle

When we last left this particular widget, I was experiencing problems with the companion button-handling widget executing more than one time per click. While my little conditional work-arounds seem to have hidden the unwanted results of that unfortunate behavior, I am still no closer to understanding how or why that is happening. In my simple mind, one click on the button should result in one execution of the activated code. Given that I don’t really know what I am doing, I may never understand why that isn’t the case, but it annoys my sense of The Way Things Ought To Be. Still, it’s probably long past time to simply move on.

Before I do, though, there is one more little enhancement that I wanted to squeeze in. Whenever I lay out a page where the content selector is on the top, instead of on the left- or right-hand side of the actual Data Table, it takes up too much vertical space and leaves a lot of unused screen real estate on either side. To change that, I added a new option to the widget called display_inline that changes the way the elements of the widget are laid out. Below is a sample use case where display_inline has been set to true.

Content selector widget in “in-line” mode

The magic to pull that off was just the addition of conditional class attributes on each of the three primary DIV elements. There was already a class attribute on each, so I could have just thrown some logic in there, but in the end I decided to leverage the AngularJS ng-class attribute instead. By adding the Bootstrap class col-sm-4 to the DIV whenever data.inline is true, the DIVs end up side by side instead of their normal stacked configuration.

    <div class="panel panel-heading" ng-class="{'col-sm-4': c.data.inline}" ng-show="c.data.config.authorizedPerspective.length > 1">
      <div align='center' class="u-space-bottom u-align-center">
        <b>Perspective</b>
        <br/>
        <span ng-repeat="p in c.data.config.authorizedPerspective" style="margin: 5px;">
          <input style="display: inline;" type="radio" name="perspective" id="{{p.name}}Perspective" value="{{p.name}}" ng-model="c.data.perspective" ng-click="selectPerspective(p.name)">
          <label style="display: inline;" for="{{p.name}}Perspective">{{p.label}}</label>
        </span>
      </div>
    </div>

    <div class="panel panel-heading" ng-class="{'col-sm-4': c.data.inline}">
      <div align='center' class="u-space-bottom u-align-center">
        <button ng-repeat="s in c.data.config.state" ng-click="selectState(s.name)" role="button" ng-class="(c.data.state==s.name) ? 'btn btn-primary btn-pressed btn-md' : 'btn btn-default btn-sm'" style="margin: 2px;">{{s.label}}</button>
      </div>
    </div>
  
    <div class="panel" ng-class="{'col-sm-4': c.data.inline, 'panel-heading': c.data.inline, 'panel-default': !c.data.inline}">
      <ul class="list-group">
        <li class="list-group-item" ng-repeat="t in c.data.list" ng-class="(t.name==c.data.table)?'highlight':''" ng-click="selectTable(t.name)">{{t.label}}
          <span class="badge">{{t.value}}</span>
        </li>
      </ul>
    </div>

To process the option, I initially default the variable value to false, and the reset it to true if the option was set to the string ‘true’.

data.inline = false;
if (options && options.display_inline == 'true') {
	data.inline = true;
}

Of course, I had to define the Display Inline option as well, but that was just a matter of updating the widget’s Option schema will a little JSON object:

[{"hint":"If selected, will display the widget content in a single row rather than a stacked block",
"name":"display_inline",
"default_value":"false",
"section":"Behavior",
"label":"Display Inline",
"type":"boolean"}]

That’s about it for allowing this to stretch out across the page rather than be stacked up in the corner. Hopefully, this will be the last you see of this unless I happen to figure out my other issue. For those of you who are interested in seeing all of the parts and pieces in detail, I have assembled everything into yet another Update Set, which you can grab from here.