2

I have the following data that I got from a third-party:

countries: [
    {"US":"United States"},
    {"CA":"Canada"},
    {"AF":"Afghanistan"},
    {"AL":"Albania"},
    {"DZ":"Algeria"},
    {"DS":"American Samoa"},
    .....
];

The way the data is organized is not how I would have done it, but now I need fit all of this in a select with ng-options so that both the value and the option displayed is the full name of the country

I have tried ng-options="code as name for (code, name) in countries" but I get an Object as my select value.

NicolasMoise
  • 7,261
  • 10
  • 44
  • 65
  • perhaps better off writing a bit to unroll the data and turn it into an array of objects that's easier to deal with http://stackoverflow.com/questions/8312459/iterate-through-object-properties could be done in the service retrieving the data. – shaunhusain Mar 18 '14 at 21:01

3 Answers3

5

Working plunkr here: http://plnkr.co/edit/nbWHz8g4Gn0vGuSHM5o0?p=preview

Though as Nicolas pointed out, it's probably better to transform the data?

HTML:

<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="angular.js@1.2.14" data-semver="1.2.14" src="http://code.angularjs.org/1.2.14/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="AppCtrl">

    <select id="countries" name="countries" ng-model="selectedCountry" 
            ng-options="getKey(country) as country[getKey(country)] for country in countries"></select>

    Selected country: {{selectedCountry}}
  </body>

</html>

JS:

// Code goes here

angular.module('app',[]).controller("AppCtrl", ["$scope", function($scope) {
    $scope.countries = [
    {"US":"United States"},
    {"CA":"Canada"},
    {"AF":"Afghanistan"},
    {"AL":"Albania"},
    {"DZ":"Algeria"},
    {"DS":"American Samoa"}
];

  $scope.getKey = function(country) {
    return Object.keys(country)[0];
  }
  }]);
Busata
  • 1,088
  • 1
  • 10
  • 24
  • This is the answer I was looking for. It's still not ideal so I guess it's better to re-work the data which is what I ended up doing anyways. I was mostly asking for theoretical reasons or if someone had a similar case where changing the data was not an option. – NicolasMoise Mar 18 '14 at 21:15
2

I was in the process of asking nearly the identical question as you when Stack Overflow suggested I look at your question. Looks like we got our Country list from the same source. I didn't want to change the structure either. But after seeing the accepted answer, I didn't want to hack it that way. So instead I wrote a reusable service that will Morph any similar data structure.

The Service

/*
 * Morphs an array of a key/val pair to have the original key, be a value, and 
 * give new property names
 *
 * @method keyValMorph
 * @param {array of objects}    ex: [ {US:'United States'} ]
 * @param {string}  keyName - desired property name for the original key
 * @param {string}  valName - desired property name for the original value
 * @return {array of objects}   ex: [ {key: 'US', val: 'United States'} ]
 */
.factory('keyValMorph', function () {
    return function (data, keyName, valName) {
    var sort = [], keyName = keyName || 'key', valName = valName || 'val';

    for (var i = 0; i < data.length; i++) {
        var obj = {};
        for (var key in data[i]) {
            obj[keyName] = key;
            obj[valName] = data[i][key];
            sort.push(obj);
        }
    }
    return sort;
    };
})

The controller call:

$scope.countriesSorted = keyValMorph($scope.countries, 'code', 'name');

It'll take your original data structure and turn it into:

$scope.countriesSorted = [
    {code:"US", name:"United States"},
    {code:"CA", name:"Canada"},
    {code:"AF", name:"Afghanistan"},
    {code:"AL", name:"Albania"},
    {code:"DZ", name:"Algeria"},
    {code:"DS", name:"American Samoa"}
];

HTML

<select data-ng-model="selected" data-ng-options="country.code as country.name for country in countriesSorted ">
    <option value="">[-- select --]</option>
</select>
EnigmaRM
  • 7,523
  • 11
  • 46
  • 72
1

Here is a sample from my own project:

data-ng-options="task.name for task in tasks track by task.id"

I am sure you can adapt it to your own.

Alex C
  • 1,334
  • 2
  • 18
  • 41
  • Well I've actually found another data source where the countries are defined as such `{name: 'AndorrA', code: 'AD'},` which works well with your example, however, your example doesn't work with my old data because I don't know what the key will be (it's not `name`). I'm still curious whether or not it's possible with this kind of data. – NicolasMoise Mar 18 '14 at 20:53
  • @NicolasMoise I think you should know what key it will be or transform your data so that you do know... – Alex C Mar 18 '14 at 20:56
  • Yea that's what I ended doing, still curious if this is possible. – NicolasMoise Mar 18 '14 at 21:00
  • @NicolasMoise It might be possible but I think it's easier to handle events in the way I described, not sure though. – Alex C Mar 18 '14 at 21:02