E-Madd
E-Madd

Reputation: 4572

AngularJS: Binding to an array, but a specific property?

I'm using this directive (wallop-slider-angularjs) and it requires an array of image urls, but my urls are properties of an array of objects. How can I bind the property in such a way that it is acceptable to the directive?

<div ng-repeat="user in users">

    <wallop-slider
        data-images="??user.media.mediumURL??"
        data-animation="rotate"
        data-current-item-index="currentSliderIndex"></wallop-slider>

</div>


media = [{'mediumURL':'http://whatever.com/image.jpg'},{'mediumURL':'http://whatever.com/image2.jpg'}]

Upvotes: 0

Views: 217

Answers (5)

chr1s1202
chr1s1202

Reputation: 467

I solved this with a custom filter:

app.filter('extractProperty', function() { 
   return function(array, propertyName) {
    return array.map(function(item) { return item[propertyName]; });
   };
});

To get an array containing the specific property you must use it like that:

<div ng-repeat="user in users">
 <wallop-slider data-images="{{ media | extractProperty:'mediumURL' }}"...></wallop-slider>
</div>

Here is a working example: http://plnkr.co/edit/WpuOCU?p=preview

Upvotes: 1

Ron
Ron

Reputation: 6725

The easiest way to do is using underscore like the following:

    <wallop-slider
        data-images="_.pluck(user.media.mediumURL, 'mediumURL')"
        data-animation="rotate"
        data-current-item-index="currentSliderIndex"></wallop-slider>

</div>

But before that you need do 2 things:

  1. add underscore

    <script src="/whatever/underscore.js"></script>

  2. inject underscorejs into controller like the folloiwng

angular.module('app', []) .controller('Ctrl', function($scope, $window) { $scope._ = $window._ });

Hope that help, Ron

Upvotes: 0

null
null

Reputation: 7926

Edit: If you already have a dependency on jQuery, I would pick Shay Friedmans answer.

I think this will do your trick (without the need for any additional libraries).

// Helper function to pluck the url property from the media items.

function pluckUrls() {
  var ret = [], c = $scope.mediaItems.length;

  while(c--) {
    ret.push($scope.mediaItems[c].url);
  }

  return ret;  
}

// Function that is called each watch cycle. The return value will differ
// if one of the urls has been modified.

function getUniqueWatchValue() {
  return pluckUrls().join();
}

// Function that is called whenever one of the urls has been modified.

function watchValueChanged() {
  console.log('One of the urls has been modified');
  $scope.mediaUrls = pluckUrls();
}

// Hook up the watch.

$scope.$watch(getUniqueWatchValue, watchValueChanged);

Plunker in action can be found here.

Note: I noticed a piece of code in that wallop-slider thingy that is watching a reference to the array, not it contents. I haven't tested it but it probably requires you to recreate the array completely instead of simply adding or removing element from it.

$scope.$watch('images', function(images) {
  if (images.length) {
    _goTo(0);
  }
});

Upvotes: 0

Mazzu
Mazzu

Reputation: 2839

You need to loop through the object along with the key and corresponding properties.

Suppose you have JS object as

var media = [
 {'mediumURL':'http://whatever.com/image.jpg'},
 {'mediumURL':'http://whatever.com/image2.jpg'}
];

Lets apply for in loop for getting values

for(key in media){
 alert(media[key].mediumURL);
}

Here "key" refers to index for media[] and "mediumURL" is the individual corresponding property.

In your case,

<div ng-repeat="user in users">

    <wallop-slider
        data-images="??user.mediumURL??"
        data-animation="rotate"
        data-current-item-index="currentSliderIndex"></wallop-slider>

</div>

Note: You were using "user.media.mediumURL", hence it wont work because "media" is not property for each object structure under media[].

You can refer to this link for more details on ng-repeat looping examples.

Upvotes: 0

Shay Friedman
Shay Friedman

Reputation: 4868

Just create a function on the scope which will extract the needed properties from the array. Something like:

scope.getMediumUrls = function(arr) {
  return $.map(arr, function(item) { return item.mediumURL; });
}

And then use it on the directive:

<div ng-repeat="user in users">
  <wallop-slider data-images="getMediumUrls(user.media)"...></wallop-slider>
</div>

Upvotes: 0

Related Questions