0

I have a $http service that retrieves user payment data. This data comes in the form of a JSON object - I asked for an array but the backend guys gave me an object! The object data structure looks something like this...

{
    creditCardData: Array[3], // this is an array of objects, each object is Credit Card data, in this case the array has 3 objects but can have many
    directDebitData: Array[0] // this is an array of objects, each object is Direct Debit data, the arrray is empty here, but the array can have unlimited objects
    errorMessage: null // this is either null or a string
    invoiceData: Array[1] // this is an array of objects, each object is Invoice data, in this case the array has 1 objects...
    paymentAvailable: true // a boolean
    selectedCreditCardData: Object // this is either an object or null
    selectedDirectDebitData: null // this is either an object or null
    selectedInvoiceData: null // this is either an object or null
}

Now I have an ng-repeat in my view and I wish to only repeat on certain items, so I wish to be able to check by key value (name) and only show the data if there is a match, so for example only show data for the keys with names 'creditCardData', 'directDebitData', 'invoiceData'.

My plan was to have a custom filter that would determine the key name/value and then add this to a new object if applicable before returning the object, something like this:

<!-- paymentData = $scope.paymentData - an object like the one above -->
<div data-ng-repeat="(key, prop) in paymentData track by $index | ObjectKeyFilter:prop:key">

And My filter (not tested) would be like so...

  .filter('ObjectKeyFilter', function () {

    return function (item, prop, key) {
      // items is the ng-repeat index, prop the data and key the name
      var tempObj = {}
      // do comparison on key create a new object... ImportantL this logic may not be correct at this stage, for explaination only
      if(key === 'directDebitData' || key === 'creditCardData' || key === 'invoiceData') {
        tempObj[key] = prop;
      }
      return tempObj;
    };
  });

Now so far I get the following error and I don't know why as I am using the track by syntax - Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: (key, prop) in paymentData track by $index | ObjectKeyFilter:prop:key, Duplicate key: undefined, Duplicate value: []

I am unsure if my approach is correct and whether a custom filter is approproate. A colleague has told me (and I have checked this in the documentation) that filters should only be used when iterating through Arrays and not with objects! My question is... is using a custom filter correct with my current situation / requirements?

Thanks in advance. If my wording is bad just add a comment and I will edit to be more clear.

2
  • less code to just map a new object in controller or service. Filters are for arrays ..yes Commented Jan 18, 2016 at 17:05
  • Duplicate key: undefined something fishy with your$scope.paymentData Commented Jan 18, 2016 at 17:05

1 Answer 1

0
app.filter('ObjectKeyFilter', function () {

    return function (item) {
      var tempObj = {}
      angular.forEach(item, function(value, key) {
        if(key === 'directDebitData' || key === 'creditCardData' || key === 'invoiceData') {
          tempObj[key] = value;
        }
      });
      return tempObj;
    };
  });

In html:

<div data-ng-repeat="(key, prop) in (data | ObjectKeyFilter) track by $index">

http://plnkr.co/edit/jITyqNmkJMiSc7NmeA19?p=preview

P.S. If you are not satisfied with data retrieved from rest call, you can just change it manually - reorder whatever, etc. I.e. in ng-resource there is transformRequest function for this.

Sign up to request clarification or add additional context in comments.

1 Comment

This answer is correct but I think you're idea about changing it manually (I'll do this is the data service) is easier than writing a filter...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.