0

I have a $scope.movies with 6 objects inside. On my template I use a ng-repeat to show the content. Which looks like this.

The movie_container divs are created by doing a "ng-repeat" = "movie in movies".

<div id="watchlist">
   <div class="movie_container"> Movie Title </div>
   <div class="movie_container"> Movie Title </div>
   <div class="movie_container"> Movie Title </div>
   <div class="movie_container"> Movie Title </div>
   <div class="movie_container"> Movie Title </div>
   <div class="movie_container"> Movie Title </div>
</div>

What I would like to do is wrap every 3 items in a container div so that the result would be,

<div id="watchlist">
   <div class="movie_wrap">
     <div class="movie_container"> Movie Title </div>
     <div class="movie_container"> Movie Title </div>
     <div class="movie_container"> Movie Title </div>
   </div>
   <div class="movie_wrap">
     <div class="movie_container"> Movie Title </div>
     <div class="movie_container"> Movie Title </div>
     <div class="movie_container"> Movie Title </div>
  </div>
</div>

Would something like this be possible to create with angular or javascript?

The $scope.movies array looks like this, (this is obviously example data, but it looks like this).

$scope.movies = [
  {
    title: 'Star Wars',
    release_date: '10-11-2015',
    movie_id: '3381',
    link: 'ePbKGoIGAXY'
  }, {
    title: 'Spectre',
    release_date: '25-12-2015',
    movie_id: '3371',
    link: 'KlyknsTJk0w'
  }, {
    title: 'Revenant',
    release_date: '02-03-2016',
    movie_id: '3361',
    link: 'nyc6RJEEe0U'
  },
    {
    title: 'Star Wars',
    release_date: '10-11-2015',
    movie_id: '3351',
    link: 'zSWdZVtXT7E'
  }, {
    title: 'Spectre',
    release_date: '25-12-2015',
    movie_id: '3441',
    link: 'ePbKGoIGAXY'
  }, {
    title: 'Revenant',
    release_date: '02-03-2016',
    movie_id: '3331',
    link: 'Lm8p5rlrSkY'
  }
];
Peter Boomsma
  • 8,851
  • 16
  • 93
  • 185
  • Right now you are repeating the same `$scope.movies` in each repeat, I'm assuming they will not all be the same in the end? If separate, would they all happen to be in one object? – ajmajmajma Dec 07 '15 at 16:11
  • Can you show your object array please? – Mike Sav Dec 07 '15 at 16:14
  • @MikeSav I've updated my question. – Peter Boomsma Dec 07 '15 at 16:17
  • @ajmajmajma I'm not sure what you mean. – Peter Boomsma Dec 07 '15 at 16:17
  • I mean right now your code doesnt make sense to me because you have 6 repeats that are repeating the **same** array. Did you mean to have 1 repeat that goes over this array once? – ajmajmajma Dec 07 '15 at 16:20
  • I've updated my html. I wanted to show that the `.movie_container` divs are created by a ng-repeat. – Peter Boomsma Dec 07 '15 at 16:22
  • this isn't really logic that is functional in the view. While you *can* use a modulo of `$index` with `ng-if`, it requires doing calculations on the `$index` in the rendering, and injects multiples of empty elements. see http://stackoverflow.com/questions/27211799/angular-ng-repeat-add-bootstrap-row-every-3-or-4-cols. If you can't use a responsive framework, you are better to divide the data in the controller. – Claies Dec 07 '15 at 16:40

2 Answers2

3

I would split the movies in the controller and then loop over the groups so I don't need to much logic in the view. controller:

var i,j,temparray,chunk = 3, movieGroups=[];
for (i=0,j=movies.length; i<j; i+=chunk) {
    temparray = movies.slice(i,i+chunk);
    movieGroups.push(temparray);
}
$scope.movieGroups = movieGroups;

markup:

<div class="movie_wrap" ng-repeat="movieGroup in movieGroups">
   <div class="movie_container" ng-repeat="movie in movieGroup">{{movie.title}}</div> 
</div>
pethel
  • 5,397
  • 12
  • 55
  • 86
  • Thanks! If you could explain the javascript a bit it would be very helpfull for me to learn some things. – Peter Boomsma Dec 07 '15 at 17:15
  • Check the documentation for Array.protoype.slice here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice. We loop through the original array with chunk steps. At each loop we create an temparray from the original array. That will be what we call a movieGroup. – pethel Dec 07 '15 at 17:39
0

You can write a function that will split them into an array of objects for you, it will make it much easier for you. See here

Fiddle example : http://jsfiddle.net/U3pVM/20670/

Something like this :

$scope.sortMoviesForWrapper = function() {
  $scope.sortedMovies = [];

  while ($scope.movies.length > 0)
    $scope.sortedMovies.push({"movies" : $scope.movies.splice(0, 3)});
};

//invoke function immediately (you can change when you do this if you need)
$scope.sortMoviesForWrapper();

I turn movies into sortedMovies with the function sortMoviesForWrapper and invoke it immediately then use the repeat on sortedMovies instead like so :

<div class="movie_wrap" ng-repeat="movieWrappers in sortedMovies">
  <div class="movie_container" ng-repeat="movie in movieWrappers.movies">
  {{movie.link}}
  </div>
</div> 

I used the movie.link so you can see they are unique. This is the basic idea. You can modify how you see fit. I created an array that has objects inside that has "movies" key for all your movies to make it easier to repeat over in the template. You don't have to use an object, or a key of movies for that matter, I just personally prefer working with it that way.

Just keep in mind, if your $scope.movie object changes, you will have to rerun this function. Hope this helps.

ajmajmajma
  • 13,712
  • 24
  • 79
  • 133
  • why would you like to put $scope.sortMoviesForWrapper(); on scope? You dont want to touch it in the view. – pethel Dec 07 '15 at 16:57
  • @user874774 I am not assuming how the user wants to consume it, possible data may change and they want access to it. Unless the movies array never changes, I would guess the user will need it in a function. Can be changed accordingly as it is an example. – ajmajmajma Dec 07 '15 at 17:05