Comment puis-je demander à AngularJS d'afficher un spinner de chargement jusqu'à ce que le chargement des données soit terminé?
Si mon contrôleur a $scope.items = [{name: "One"}]
configuré statiquement, et un chargeur AJAX qui remplit $scope.items[0]['lateLoader'] = "Hello"
, J'aimerais que le spinner s'affiche jusqu'à ce que la charge AJAX soit terminée, puis remplit la plage liée avec les données récupérées.
<ul ng-repeat="item in items">
<li>
<p>Always present: {{item.name}}</p>
<p>Loads later: <span ng-bind="item.lateLoader"><i class="icon icon-refresh icon-spin"></i></span></p>
</li>
</ul>
Ce code remplit immédiatement la plage liée et comme item.lateLoader
est vide, le spinner est remplacé par rien.
Comment dois-je procéder proprement?
Je créerais une directive personnalisée selon l'autre réponse, mais voici comment vous pouvez le faire sans la directive, ce qui pourrait être une bonne idée d'apprendre avant d'entrer dans des fonctionnalités plus complexes. Quelques choses à noter:
Démo: http://plnkr.co/edit/4XZJqnIpie0ucMNN6egy?p=preview
Vue:
<ul >
<li ng-repeat="item in items">
<p>Always present: {{item.name}}</p>
<p>Loads later: {{item.lateLoader}} <i ng-hide="item.lateLoader" class="icon icon-refresh icon-spin">loading image i don't have</i></p>
</li>
</ul>
Manette:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.items = [{name: "One"}];
setTimeout(function() {
$scope.$apply(function() {
$scope.items[0].lateLoader = 'i just loaded';
});
}, 1000);
});
En fait, j'utilise une solution pour cela depuis un certain temps maintenant, qui fonctionne très bien et qui vaut mieux que d'utiliser un délai d'attente à mon avis. J'utilise $ resource, mais vous pourriez faire la même chose avec $ http. Sur mes objets de ressources $, j'ajoute le bit dans le code suivant qui définit chargé à true.
$scope.customer = $resource(dataUrl + "/Course/Social/" + courseName)
.get({}, function (data) { data.loaded = true; });
Ensuite, à mon avis, je peux utiliser:
ng-hide="customer.loaded"
Bien sûr, je n'utiliserais pas une ressource $ directement dans un contrôleur, je l'extrait vers un service customerRepository, mais c'était plus simple de le montrer ici.
Je créerais une directive personnalisée et mettrais un balisage par défaut avec spinner.
Voici quelques liens sur les directives personnalisées
1) Les vidéos Egghead sont géniales! http://www.egghead.io/video/xoIHkM4KpHM
2) Documents officiels Angular on directives http://docs.angularjs.org/guide/directive
3) Bon aperçu de angular en 60 minutes) http://weblogs.asp.net/dwahlin/archive/2013/04/12/video-tutorial-angularjs-fundamentals- in-60-ish-minutes.aspx
@lucuma,
Excellente réponse, une alternative peut être d'injecter $ timeout et de remplacer la fonction native timeout:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout) {
$scope.name = 'World';
$scope.items = [{name: "One"}];
$timeout(function() {
$scope.$apply(function() {
$scope.items[0].lateLoader = 'i just loaded';
});
}, 1000);
});