Chamadas de API e rolagem infinita com AngularJS

Este fim de semana, tenho brincado um pouco com o AngularJS e devo dizer que estou muito surpreso com isso. Para ilustrar como pode ser simples, vou mostrar um exemplo mínimo para carregar imagens de uma API quando o usuário rola para baixo.

Primeiro, vamos dar uma olhada no HTML:

<!DOCTYPE html>
<html>
<head>
<title>Some dummy example</title>
<script type="text/javascript" src="/static/js/vendor/angular-1.0.6.min.js"></script>
<script type="text/javascript" src="/static/js/files_controllers.js"></script>
</head>
<body ng-controller="FilesListCtrl" ng-app="my-awesome-app">
<div class="container" when-scrolled="loadImages()">
<h2>Images</h2>
<ul class="images">
<li ng-repeat="image in images">
<img ng-src="{{ image.thumbnailLink }}">
{{ image.title }}

</li>
</ul>
</div>
</body>
</html>

Muito simples, não é? Alguns comentários:

Nós adicionamos à tag. Dessa forma, “permitimos” que o AngularJS trabalhe sobre ele e faça sua mágica. Além disso, adicionamos um controlador chamado que iremos escrever. No AngularJS, um controlador é uma função que assume a . Essa função pode fazer quase tudo o que você quiser e você pode adicionar o que quiser a ela. O legal é que tudo o que você adicionar ao escopo estará acessível a partir dos modelos.ng-appbodyng-controllerFilesListCtrl$scope

Então, nós temos . Vinculamos esse evento a uma função que escreveremos em nosso código JS.when-scrolled="loadImages()"

Por último, temos este pedaço de código:

<li ng-repeat="image in images">
<img ng-src="{{ image.thumbnailLink }}">
{{ image.title }}

</li>

A diretiva é basicamente um loop for in , portanto, estamos iterando sobre uma variável chamada e, para cada uma delas, adicionamos um com uma imagem e seu título. Observe que estamos usando em vez de . Basicamente, é para não obter um erro de DOM o tempo todo.ng-repeatimages<li>ng-srcsrc

Finalmente, vamos dar uma olhada no arquivo JS:

function FilesListCtrl($scope, $http) {

$scope
.images = [];
$scope
.next_page = null;
var in_progress = true;

$scope
.loadImages = function() {
if (in_progress){
var url = '/api/v1/files.json';
if ($scope.next_page) {
url
= $scope.next_page;
}
$http
.get(url).success(function(data) {
$scope
.images = $scope.images.concat(data.items);
$scope
.next_page = data.nextPageInternal;

if (!$scope.next_page) {
in_progress
= false;
}
});
}
};

FilesListCtrl.$inject = ['$scope', '$http'];

$scope
.loadImages();
}

Este primeiro pedaço é o próprio controlador. É executado quando a página é carregada e basicamente o que estamos fazendo é fazer uma chamada de API e adicionar as imagens . Assim poderemos acessá-los através do HTML que vimos antes. A linha é necessária para superar alguns problemas com minimização.$scope.imagesFilesListCtrl.$inject = ['$scope', '$http'];

Também temos lá:

angular.module('my-awesome-app', []).directive('whenScrolled', function() {
return function(scope, elm, attr) {
var raw = elm[0];

elm
.bind('scroll', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope
.$apply(attr.whenScrolled);
}
});
};
});

Desta forma, vinculamos a diretiva whenScrollede disparamos a função que marcamos no DOM. Com a lógica apropriada , obteremos um efeito realmente “semelhante ao do interesse” ao rolar.loadImages()

Fácil, não é?