Using value-properties in TabbedBars

A TabbedBar is an iOS-only control known in the native API as UISegmentedControl, which is basically multiple buttons attached to each other:

UISegmentedControl

A fine UX to have the user choose between just a few options.

Creating a TabbedBar

The control has a labels property which accepts an array to set the titles of the buttons (labels) and an index property to set and get the selected label, which is also given in the click event. In Alloy, you set the labels like this:

<Alloy>
  <Window>
    <TabbedBar id="field">
      <Labels>
        <Label title="Paid" value="paids" />
        <Label title="Free" value="frees" />
        <Label title="Top Grossing" value="cows" />
      </Labels>
    </TabbedBar>
    
  </Window>
</Alloy>

Why the value?

You’ll notice I also use a value property on the labels. Wasn’t labels an array of just strings? Well, yes it can be, but it can also be an array of dictionaries adhering to the BarItemType. This allows you to use images instead of titles, set the width per label, but also – like on any proxy element – set custom properties.

From index to value

Having the value stored in the label allows you to do:

// this
var value = $.field.labels[$.field.index].value;

// instead of
var value;
switch ($.field.index) {
  case 0: value = 'paids'; break;
  case 1: value = 'frees'; break;
  case 2: value = 'cows'; break;
}

This may remind you of doing var value = field.options[field.selectedIndex] in the browser and just like <option value="frees">Free</option> in HTML the view’s XML is very clear about both the labels and values.

Reading and writing properties

If you’d have a settings window with lots of tabbars, you could read and write Ti.App.Properties without having to change anything when adding a new setting with something like this in the controller:

var fields = ['field_a', 'field_b', .., 'field_z']

function read() {

  _.each(fields, function(field, name) {
    var value = Ti.App.Properties.getString(name);

    _.some($[name].labels, function(label, index) {
      if (label.value === value) {
        $[name].index = index;
        return true;
      }
    });
  });
}

function write() {

  _.each(fields, function(field, name) {
    Ti.App.Properties.setString(name, $[name].labels[$[name].index].value);
  });
}

Stay DRY!

App imagineer: Imagining, Engineering & Speaking about Native mobile Apps with Appcelerator Titanium & Alloy • Meetup organizer • Certified Expert • Titan