Question

I have a user object and an array of events:

$scope.user = {
  userId: 2,
  userName: jdoe,
  eventIds: [23,34,45]
}

$scope.events = [
  {eventId: 23, eventName:"bar"},
  {eventId: 34, eventName:"baz"},
  {eventId: 45, eventName:"qux"}
  {eventId: 56, eventName:"..."},
]

When displaying the user details, I'd like to list all the events. I can display the eventIds easily:

<span ng-repeat="eventId in user.eventIds">{{eventId}}</span>

I'd like to display the events by their name. I've managed to find a solution with help from underscorejs:

<span ng-repeat="eventId in user.eventIds">{{getEventName(eventId)}}</span>

$scope.getEventName = function (eventId) {
  return _.findWhere($scope.events, { eventId: eventId }).eventName;
}

While this works, it seems cumbersome, especially when I find myself repeating this over and over for different objects, and I'd imagine there are major performance implications as well.

Is there a better "angular way" to help me resolve the event names?

Was it helpful?

Solution

Similar to what John Munsch said, you can create a "map" of your events beforehand so that you don't have to keep calling a function to get your event name. Underscore even provides a function that makes it easy to do.

in your controller

$scope.eventsById = _.indexBy($scope.events, "eventId");

in your html

<span ng-repeat="eventId in user.eventIds">{{ eventsById[eventId].eventName }}</span>

What I like better about this method is that you only need to loop through your events array once, John's answer will do one loop per change in user.eventIds and your current solution does a loop for every single output of ng-repeat

OTHER TIPS

There's nothing I can think of that AngularJS does that makes that any better. But I can say that it might be more optimal to do something like this:

<span ng-repeat="event in mappedEvents(user.eventIds)">{{event.eventName}}</span>

$scope.mappedEvents = function (eventArray) {
  // Map the array of IDs to actual event objects and return an array of those event objects.
}

Since you're only doing all of the mapping once for the entire array of events you might get better results. You can use sorting or other methods to make that faster.

You could add an array of events to the user object which reference the events in the events array:

$scope.user.events = _.map($scope.user.eventIds, function(eventId){
    return _.findWhere($scope.events, {eventId: eventId});
});

and then just iterate over these events in the view:

<span ng-repeat="event in user.events">{{event.eventName}}</span>

Fiddle

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top