简体   繁体   中英

AngularJS Nested Object Array Pathway

I have a factory, which goes into a controller, and I am trying to get data from that display on an HTML page. I am having trouble specifying an Object's pathway however.

My Factory:

app.factory('APIMethodService', function() {
  var Head = "api.example.com";
  return {
    apis: 
    [{
      accounts: [
        {
          v1: [
            {
              uri: Head+"/v1/accounts/",
              item1: "AccountNumber",
              item2: "MoneyInAccount"
            }],
            v2: [
            {
              uri: Head+"/v2/accounts/",
              item1: "AccountNumber",
              item2: "MoneyInAccount"
            }]
        }
      ],
      customers: [
        {
          v1: [
            {
              uri: Head+"/v1/customers/",
              item1: "CustomerName",
              item2: "CustomerID",
              item3: "CustomerEmail"
            }]
        }
      ]
    }]
  };
});

My Controller:

app.controller('APIController', function($scope, APIMethodService) {
$scope.title = "API";
  $scope.apiList = APIMethodService;
  $scope.accountList = $scope.apiList.accounts.v1;
  $scope.accountList2 = $scope.apiList[0][0];
});

My HTML

<div ng-controller="APIController">

<div id="api" class="row">
  <div class="col-xs-12">
    <div class="row" style="font-size:20px">
      {{title}} Page!
      <table class="table table-striped">
        <tr ng-repeat="api in apiList | orderBy:'uri' | filter:search">
           <td>{{api.uri}}</td>
           <td>{{api.item1}}</td>
           <td>{{api.item2}}</td>
        </tr>
      </table>
    </div>
  </div>
</div>

</div>

The errors I get are in regards to the Controller trying to parse out the individual objects I wish to grab, like accounts or customers , and then any version v# , they may have.

So it will say something such as

TypeError: Cannot read property 'v1' of undefined

I just need some help specifying the proper pathways into my factory service.

You have a few problems. First, you are referring to the object returned from the factory incorrectly. APIMethodService is the factory that you're injecting, so you need to first reference the object that that factory is returning like this:

APIMethodService.apis

This will give you your entire JSON object.

From there, the rest of your object is made up of arrays of objects, so referring to 'v1' won't do you any good. You need to specify an index instead. If you want v1, you'll need:

APIMethodService.apis[0].accounts[0].v1

This will give you the v1 array, which again is an array of objects.

Customers would be:

APIMethodService.apis[0].customers[0].v1

The first problem you have is that the factory returns an object with a single property called apis . So basically this $scope.apiList.accounts.v1 should be $scope.apiList.apis.accounts.v1 . Bu that's not all as this won't either work since dotting(.) into apis is an array you'd have to use the index. In this case it would be $scope.apiList.apis[0] and then you could .accounts[0].v1 which is also an array containing a single object.

Now if you can I would suggest to you that you'd change how you represent this data structure.

This is how you could do it.

app.factory('APIMethodService', function() {
    var Head = "api.example.com";
    return {
        accounts: {
            v1: {
                uri: Head+"/v1/accounts/",
                items: ["AccountNumber","MoneyInAccount"]
            },
            v2: {
                ... // skipped for brevity
            }
        },
        customer: {
           ... // code skipped for brevity
        }
    };
});

And then it's just a matter of dotting into your APIMethodService-object like APIMethodService.accounts.v1.items[0] if you want the AccountNumber method name.

Constructing your url could then be done like this.

var baseUrl = APIMethodService.accounts.v1.uri; // 'api.example.com'
var url = baseUrl + APIMethodService.accounts.v1.items[0]; // 'AccountNumber'
// url = "api.example.com/v1/accounts/AccountNumber"

Again, this is one way you could do it but this can be further enhanced upon. The examples I provided are simply for demo purposes and this is not in any way the only way to do it.

Expanding upon recieved comments/questions your service (and data representation) could now look like this.

app.factory('APIMethodService', function() {
    var Head = "api.example.com";
    return {
        accounts: {
            v1: {
                uri: Head+"/v1/accounts/",
                items: [
                    {
                        name:'AccountNumber',
                        description:'Show the account number'
                    },
                    {
                        name:'AccountOwner',
                        description:'Show information about the owner of the account'
                    },
                    {
                        name:'MoneyInAccount',
                        description:'Show money in the Account'
                    }
                ]
            },
            v2: {
                ... // skipped for brevity
            }
        },
        customer: {
           ... // code skipped for brevity
        }
    };
});

// Get descriptions
var accountNumberDescription = APIMethodService.accounts.v1.items[0].description; // 'Show the account number'
var accountOwnerDescription = APIMethodService.accounts.v1.items[1].description; // 'Show information about the owner of the account'
var moneyInAccountDescription = APIMethodService.accounts.v1.items[2].description; // 'Show money in the Account'

By using objects with properties like this it's alot easier to understand what you are trying to do. With arrays with indexes you'd have to know or take a look at the source to see what's going on. Here, someone viewing your code they can instantly understand that it is the description you are getting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM