3

I'm trying to create a infinite scroll feature in my application but it feels a bit abstract. I want to use ui-scroll and this fiddle shows a simple example of how it works.

I've read the readme and looked through some examples also I've integrated the example in my project and got it working, but I can't figure out on how to combine this with data from my own database.

I have a database table called movies. The movies have a few values such as title, release_date, image_url

How would I insert that data into the $scope.movieDataSource so I can use it in my view?

$http.get(('/movies.json'), {
    cache: true
  })
  .success(function(data, status, headers, config) {
    if (status == 200) {
      $scope.userMovies = data;
    } else {
      console.error('Error happened while getting the user list.')
    }
    $scope.movieDataSource = {
      get: function(index, count, callback) {
        var i, items = [$scope.userMovies], item;
        var min = 1;
        var max = 1000;

        for (i = index; i < index + count; i++) {
          if (i < min || i > max) {
            continue;
          }
          item = {
            title: $scope.userMovies.title,
            imageURL: $scope.userMovies.poster_path
          };
          items.push(item);
        }
        callback(items);
      }
    }
  });

I've tried to create an example of what I'm trying to get at. I use a http.get to fill my userMovies scope with records from my database and I want to use those records as items in the movieDataSource.

But when I visit the page I that ui-scroll does add results in the container, but it does not show content.

<div class="imageCell ng-scope" ui-scroll="item in movieDataSource">
  <img title="">
</div>

If I console.log("movieDataSource" + $scope.movieDataSource) it shows me movieDataSource[object Object].

dhilt
  • 13,532
  • 6
  • 48
  • 67
Peter Boomsma
  • 5,330
  • 5
  • 56
  • 111
  • the code you posted here and the fiddle you provided seem to work correctly. What is the issue you are trying to work out here? does setting `item` equal to your data not serve your purpose? – Claies Oct 12 '15 at 14:30
  • @Claies I'm trying to figure out how I can use data from my own database as items in the `movieDataSource` so I can show those records in my view instead of the numbers that are generated now. – Peter Boomsma Oct 12 '15 at 14:33
  • I'm still not clear on what data you have, but it seems like the only thing you would have to change is the `item =` assignment call. – Claies Oct 12 '15 at 14:36
  • something like `item = yourData[i];` if `yourData` was an array you already have.... – Claies Oct 12 '15 at 14:38
  • I have a database table called `movies` inside that table are 1000 records, each record has a `title`, `release_date`. I want to display that data in my view through the `movieDataSource` – Peter Boomsma Oct 12 '15 at 14:49
  • right, so **how are you retrieving those 1000 records now?** This function just takes the individual items and pushes them to an array; I'm not sure why you don't know how to do the same with your own items, since this is pretty standard JavaScript. – Claies Oct 12 '15 at 14:51
  • Instead of showing someone else's code and asking how to make it your own, you should instead present your own code that represents your failed attempts and ask how to fix it. – Claies Oct 12 '15 at 14:54
  • I retrieve the records through the `ng-repeat` function from AngluarJS and insert them directly into the view. `.movie_container{"ng-repeat" => "movie in movies"` – Peter Boomsma Oct 12 '15 at 14:54
  • well `ng-repeat` doesn't "retrieve" records, it iterates through them. It also doesn't "insert" them anywhere, it renders the items being iterated. Based on this latest comment, it seems like you already have an array on `$scope` called `movies`, so I go back to my earlier comment, `item = $scope.movies[i];`..... – Claies Oct 12 '15 at 14:56
  • @Claies I've tried to create an example of how I want it work. – Peter Boomsma Oct 12 '15 at 15:40
  • you didn't add any content to your HTML that you posted there. it should be the same as if you were using `ng-repeat`, i.e. `{{item.title}}`. – Claies Oct 12 '15 at 15:45
  • it really seems you need to study a bit more about how angular, and JavaScript in general, work. – Claies Oct 12 '15 at 15:46
  • and your update to the JavaScript function isn't anything like what ***I posted TWICE***. The you wrote code has no way of identifying **which** movie title you want, since it doesn't reference the loop counter (`i`). – Claies Oct 12 '15 at 15:55
  • Angular and Javascript even more so are so big it's hard to begin somewhere. I've done some Angular and Javascript codescool courses but you will always run into problems no matter how much you learn. My learning course is best by example. Do, fail. Do, fail again. Do, fail another time. Do, hey something is working. Of 90% of my questions is learn the solution or get insight in how to aproach the problem differently so I can try something else. In this case it's too abstract for me. I can't understand there is no example on how to use `ui-scroll` with data from your own database. – Peter Boomsma Oct 12 '15 at 16:15
  • There are definitely examples of how to use this with your own data, https://github.com/angular-ui/ui-scroll/tree/master/demo/examples. I did, however, work up an answer that may help you get going in the right direction. – Claies Oct 12 '15 at 16:39

2 Answers2

8

You are making this more complex than necessary. The uiScroll directive is a replacement for ngRepeat, which takes a Data Source with 3 properties:

  • index indicates the first data row requested
  • count indicates number of data rows requested
  • success function to call when the data are retrieved. The implementation of the service has to call this function when the data are retrieved and pass it an array of the items retrieved. If no items are retrieved, an empty array has to be passed.

in your case, you have an array of items. Each time the index or count changes, the success fires, and this function should return a subset of your array from index to index + count. There are multiple ways to accomplish this. The example you posted uses a for loop to iteratively push items into the array. You could also use the Array.slice() method.

Option 1:

 $scope.movieDataSource = {

   get: function(index, count, callback) {
     var i, items = [], item;

     for (i = index; i < index + count; i++) {
       item = $scope.userMovies[i];
       items.push(item);
     };

     callback(items);
   }
 }

Option 2:

 $scope.movieDataSource = {

   get: function(index, count, callback) {
     var items = $scope.userMovies.slice(index, index + count);
     callback(items);
   }
 }

As for your HTML, it should be identical to if you were using ng-repeat:

<div ui-scroll="item in movieDataSource">
  {{item.title}}
  <img title="{{item.title}}" ng-src="{{item.poster_path}}"></img>
</div>
Claies
  • 21,481
  • 3
  • 49
  • 75
  • Thank you for taking the time help me understand the issue. http://jsfiddle.net/q4xstonz/10/ is pretty much what I wanted, except I just saw you can't filter or use orderBy since it's not Angular. It looks like I need to order the array in the controller. I always thought I could get by with my little JS knowledge, and I could when I was only using jQuery, but now I'm diving more and more in Angular it looks like I really need to get more knowledge of Javascript. – Peter Boomsma Oct 12 '15 at 17:30
  • you won't be able to filter or order the `movieDataSource` because it is not bound to your entire array, it is only bound to the *subset* of the array that is currently visible. That's the way that directive works, it adds items to the DOM as you scroll, and removes items that go out of view, which means you don't have two way binding anymore, so yes, you would have to filter or order `userMovies` instead. – Claies Oct 12 '15 at 17:38
  • shouldn't `callback(items);` be enclosed within the `get` function? – Luke Hutton Jan 31 '17 at 20:52
  • @LukeHutton I don't really recall what I was doing in 2015 when I wrote that logic, but clearly I had both functions wrong; thanks for identifying my mistake. – Claies Jan 31 '17 at 21:41
0

Apparently ui-scroll calls the given object "movieDataSource" with an index and a count. It then expects the function to push all items between index and index + count in the returned array.

That means that you have to implement code that fetches the respective items from your DB (via REST or however you access your data) and insert the returned records in the items array.

Andre Kreienbring
  • 2,317
  • 9
  • 15
  • I've updated the question with an example of how I think it might work, but it's not showing the needed result. Could you maybe give some feedback? – Peter Boomsma Oct 12 '15 at 15:43