Monday, October 10, 2011

angular select list options

Angular allows filling in of selection lists via different data structures, but can be a bit confusing as to how to build them sometimes.

I have had to make certain data structures available as angular services to our developers, making the calls as simple as possible.

Say we have a straight JSON object such as:

{
  "33":"Bed",
  "44":"Call",
  "66":"Emergency"
}

I take this call from an $xhr request:

getDatasets: function(ctrl) {
  $xhr("GET", CURRENT_DATASETS_URL,
    function (code, response) {
      processDatasets(ctrl, code, response);
    },
    function (code, response) {
      processDatasets(ctrl, code, {});
      showError("Unable to load ...");
    }
)};

and inside 'processDatasets()' method - manipulate data structure so turns out such as:

self.datasetsArray = [
  {label:"Bed",value:33},
  {label:"Call",value:44},
  {label:"Emergency",value:66}
]

We can render a select list easily with:

<select name="dataset" ng:model="form.dataset" required 
        ng:options="ds.value as ds.label for ds in datasetsArray">
</select>

Giving us the labels and values needed.

Another challenge for this came up as wanting to utilize groups for values as well. For example, a structure coming in from a service call would come back as:

{
  "MainMenu":  {"Menu Item 1": 5},
  "AlertMenu": {"Alert Item 1": 9, 
                "Alert Item 2": 2, 
                "Alert Item 3": 7, 
                "Alert Item 4": 23
  },
  "TrackMenu": {"Track Item 1": 55, 
                "Track Item 2": 1, 
                "Track Item 3": 8, 
                "Track Item 4": 6, 
                "Track Item 5": 10, 
                "Track Item 6": 3
  }
}

Manipulating this structure in our callback from the service (like above), we create an array such as:

var menuGroups = [
  {group:"MainMenu", label:"Menu Item 1", value:5},
  {group:"AlertMenu", label:"Alert Item 1", value:9},
  {group:"AlertMenu", label:"Alert Item 2", value:2},
  ...
  {group:"TrackMenu", label:"Track Item 1", value:55},
  {group:"TrackMenu", label:"Track Item 1", value:1},
  ...
]

We can now use this to create a select menu with the 'optgroup' already in place:

<select name="menuPage" ng:model="form.menuPage" ng:format="number" required 
        ng:options="mp.value as mp.label group by mp.group for mp in menuGroups">
  <option></option>
</select>

** Updated for changes in form processing with angular 0.10.3+.