3

What in your opinion is the best way to display complex objects in AngularJS?

You have some sort of return from a service used in multiple places in a app and you might have to display multiple properties, each with a specific filter in each place.

With a quick thought I can name 3 different ways but I'm just not sure if any of them is the best way or how to implement them.

Plunker

Sample (and simple) object

Lets say I have to display this object like this: John SMITH ($30.00).

{
    firstName: 'John',
    lastName: 'Smith',
    pocket: 30
}

I could easily go

{{person.firstName}} {{person.lastName | uppercase}} ({{person.pocket | currency}})

But what if I have it as a attribute somewhere, like in a ng-option

Long string

So I would need to do this

<select ng-options="(p.firstName + ' ' + (p.lastName | uppercase) + ' ' + '\(' + (p.pocket | currency) + '\)') for p in persons" ng-model="person"></select>

This is way to long and not very readable, if the same sort of formatting is going on in other places it isn't very DRY either.

Function

I could go the function route with this

$scope.formatPerson = function(person) {
    return person.firstName + ' ' + $filter('uppercase')(person.lastName) + ' ' + '\(' + $filter('currency')(person.pocket) + '\)';
}

-

<select ng-options="(formatPerson(p)) for p in persons" ng-model="person"></select>

Long, but hidden behind so not as much of a problem. But if i'm defining this on the controller it again isn't very DRY, where would a function like this belong? In the service that gives the object?

Filter

This one I like best

app.filter('person', function($filter) {
  return function(person) {
    return person.firstName + ' ' + $filter('uppercase')(person.lastName) + ' ' + '\(' + $filter('currency')(person.pocket) + '\)';
  }
});

Sure I would need to add some guards against things that aren't person objects, but should filters be used against complex objects, are they made for primitives only. Could more complex objects lead to slowdowns as the filter is constantly running through the object tree?


Are there more ways to do this, or is one of these ways the best and correct way?

0

CacheFactory would be the most portable and easiest to debug:

function sharedCache($cacheFactory)
   {
   var sharedCache = $cacheFactory.get('sharedCache') ? $cacheFactory.get('sharedCache') : $cacheFactory('sharedCache');

   return sharedCache;
   }

function bar(sharedCache)
   {
   var data = {
     firstName: 'John',
     lastName: 'Smith',
     pocket: 30
     };

   sharedCache.put('sharedCache', data);
   }

bar.$inject = ['sharedCache', '$scope'];
sharedCache.$inject = ['$cacheFactory'];

angular.module('foo',[]);
angular.module('foo').constant('sharedCache', sharedCache);
angular.module('foo').run(bar);

Filters can read the data and output using ng-include and the templateCache. For example:

function bop(name)
  {
  var data = baz.data.get('sharedCache');
  var tmpl = '';

  try
     {
     tmpl = tmpl.concat('<h1>',data.firstName, '</h1>');
     baz.tmpl.put(name, tmpl);
     }
  catch(e)
     {
     console.log(e);
     }
  }

function baz($templateCache, sharedCache)
  {
  baz.tmpl = $templateCache;
  baz.data = sharedCache;
  return bop;
  }

baz.$inject=['$templateCache', 'sharedCache'];
angular.module('foo').filter('baz', baz);

With this markup:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="foo">
  <div ng-include="'userContent' | baz"></div>
</div>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.