Steve
Steve

Reputation: 14912

AngularJS: get object property in array by matching a different property?

I have an array of products, displayed in a table with an AngularJS ng-repeat.

The products are an array of objects returned from a Wordpress REST API call, and each object has a "category", which returns as a number.

Example: { "name": "Foo", "cat": 12 }

I can't simply bind to the "cat" property, since it displays "12" and I want to display the category label instead.

I can query for the list of all categories, and get an array like so:

[
    { label: 'Customer Engagement Solutions', id: 2 },
    { label: 'Small and Medium Business', id: 13 },
    { label: 'Customer Information Management', id: 4 },
    { label: 'eCommerce', id: 25 },
    { label: 'Location Intelligence', id: 16 },
    { label: 'Enterprise', id: 12 }
]

My product above, "Foo" should display "Enterprise", which is 12.

I know I can bind to a function, as in {{ctrl.getCat(product)}} but I'm not sure how to do the matching of the ID in the product to the one in the category array, and return the category label.

This is trivial to do in actual Wordpress PHP as they provide a function for this very task.

Upvotes: 1

Views: 2217

Answers (2)

Hoyen
Hoyen

Reputation: 2519

The easiest way would be to create a new array of products that already maps the categories. When you initialize the controller with the products and categories, create a new array the maps it.

var app = angular.module('app', []);

app.controller('MainCtrl', function($scope) {

  const _categories = [
    { label: 'Customer Engagement Solutions', id: 2 },
    { label: 'Small and Medium Business', id: 13 },
    { label: 'Customer Information Management', id: 4 },
    { label: 'eCommerce', id: 25 },
    { label: 'Location Intelligence', id: 16 },
    { label: 'Enterprise', id: 12 }
  ];
  
  const _products = [
    { "name": "Foo", "cat": 12 },
    { "name": "Bar", "cat": 16 },
    { "name": "Foo Bar", "cat": 12}
  ]
  
  let categoryMap = {}
  
  _categories.forEach( (category)=>{
    categoryMap[category.id] = category.label;
  })
  
  this.products = _products.map( (product)=>{
    return {
      "name": product.name,
      "category": categoryMap[product.cat]
    }
  })
  
  
});
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script data-require="[email protected]" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
  </head>

  <body ng-controller="MainCtrl as ctrl">
    <div ng-repeat="product in ctrl.products">
      <span>Name: {{product.name}}</span>&nbsp;<span>Category: {{product.category}}</span>
    </div>
  </body>

</html>

Upvotes: 0

charlietfl
charlietfl

Reputation: 171669

Use Array#find() or even more performant is create a hashmap of the category labels using id as property keys

Using find()

ctrl.getCat = function(product){
  let cat = categories.find(e => e.id === product.cat)
  return cat ? cat.label : 'Unknown';
} 

Or as hashmap:

ctrl.catLabels = categories.reduce((a,c) => { a[c.id] = c.label; return a;},{})

Then in view:

{{ctrl.catLabels[product.cat]}}

Upvotes: 1

Related Questions