问题
I've an image gallery site where I'm getting all images and image related data from the database as json format in my controller and then by using ng-repeat I'm binding them with the html. Now, data are loaded early but images are loaded late, so images are scattered. How to solve this. I don't want to use setTimeOut.
The sample code is as below:-
<!DOCTYPE html>
<html lang="en" class="no-js" ng-app="cps">
<body ng-controller="CPSController">
<div>
<li ng-repeat="image in images" class="shown">
<a id="{{image.imageid}}" ng-click="openimage(image.imageid)">
<img idx="id-thumb-{{$index}}" ng-src="/imagedisplay/{{image.imageid}}" alt="" style="">
<div class="meta_info">
<h3>{{image.imagename}}.</h3>
<div class="callto">
<div class="actions">
<span><img src="img/artist.svg" alt="">{{image.ownername}}</span>
<span><img src="img/likes.svg" alt="">{{image.likes}}</span>
<span><img src="img/views_small.svg" alt="">{{image.views}}</span>
</div>
<div class="category">
Art Category
</div>
</div>
</div>
</a>
</li>
</div>
</body>
</html>
<script>
var cps = angular.module('cps', []);
cps.controller('CPSController', function($scope, $http, $compile){
$scope.products = [];
$http.get("/alldata/").success(function(data){
if(data != "null")
{
for(i=data.length-1; i>=0; i--){
$scope.products.push(data[i]);
}
$scope.sendOrder('views', 'likes', 'timestamp', 2);
}else{
//$('#noImages').show();
}
/*setTimeout(function(){
$("[idx^='id-thumb']").show();
});*/
});
});
</script>
回答1:
# UPDATE [August 2017]
Same answer as below except we could work with the load
event on window
instead of DOMContentLoaded
on document
. This will ensure that all assets (such as images) in the window
are loaded.
window.addEventListener("load", function(event) {
...
})
We don't have to force Angular where vanilla javascript
can suffice. This is how it worked for my AngularJS
project
Added this to the body tag. It will be removed with a script tag once HTML Content Loads
<div id="page-loading">
<img style="display:block; margin:0 auto;" src="styles/img/page-loading.gif">
</div>
script
tag right under the image.
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
/*VANILLA JAVASCRIPT*/
var element = document.getElementById("page-loading");
element.parentNode.removeChild(element);
/* OR WITH jQuery*/
$('#page-loading')
.fadeOut('slow');
});
</script>
DOMContentLoaded
event will ensure that the the callback
is executed when all the images,fonts,js and other assets
have been loaded.
Good Luck.
回答2:
I'm not sure if this is the right approach, but what I usually do is that I have a $scope.loaded
variable which has the state of the page. If the page is loaded, the div you want to show is shown... If it's loading, the div with the loader is shown. Have a look at this plunk to get what I'm trying to say.
I'm pasting the Plunkr code here as well.
Javascript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout) {
$scope.loaded = true;
$scope.text = 'Nothing loaded yet.';
$scope.loadSomething = function () {
$scope.loaded = false;
$timeout(function() {
// Simulates loading
$scope.text = 'Hello World';
$scope.loaded = true;
}, 2000);
};
});
HTML
<body ng-controller="MainCtrl">
<button class="btn btn-primary" ng-click="loadSomething()">Load Something</button>
<br/>
<div ng-hide="loaded">
Loading...
</div>
<div ng-show="loaded">
<p>{{ text }}</p>
</div>
Do let me know if you need any further help.
回答3:
Try this:
angular.element($window).bind('load', function() {
$scope.yourLoaderDiv=true;
});
回答4:
I have struggled with same issue. Here is what working on my side where i am showing multiple loading image for each different section based on promise. For this purpose i have created a directive.
My html looks something like below.
<mi-loading promise="Loading"></mi-loading>
Angularjs directive.
(function () {
var module = angular.module('mi-loading', []);
module.directive('miLoading', function () {
return {
restrict: 'E',
scope: {
promise: '='
},
link: function ($scope, $element, $attrs) {
$scope.IsLoading = true;
$scope.$watch('promise', function (prom) {
if (!prom) {
$scope.IsLoading = false;
return;
}
prom.success(function () { $scope.IsLoading = false; });
});
},
template: '<div ng-show="IsLoading" class="spinner" style="height:300px"></div>'
};
});
})();
and finally the usage,
var getData = function ()
{
var Promise = myservice.getMyData($scope);
$scope.Loading = Promise;
};
CSS
.spinner {
min-width: 30px;
min-height: 30px;
}
.spinner:before {
content: 'Loading…';
position: absolute;
top: 50%;
left: 50%;
width: 24px;
height: 24px;
margin-top: -13px;
margin-left: -13px;
}
.spinner:not(:required):before {
content: '';
border-radius: 50%;
border: 3px solid #ccc;
/*border-top-color: #03ade0;*/
border-top-color: #4187b5;
animation: spinner .6s linear infinite;
-webkit-animation: spinner .6s linear infinite;
}
回答5:
To achieve it, i am loading all my scripts at the end of the body. Before my app-wrapper-div i place a postion fixed "loading"-div. It is shown immediately before other scripts are loaded.
At the end of the body, after my scripts are included, i place an angular directive, that fadeOut and remove the loading-div.
The code:
<html ng-app="myApp">
<head>
<!-- the only file loaded in the head -->
<link rel="stylesheet" href="/.../appLoadingScreen.css"/>
</head>
<body>
<div id="appLoadingScreen">
<div id="appLoadingScreenCenterWrap">
<h1 id="appLoadingScreenHeader">APP TITLE</h1>
<p id="appLoadingScreenMsg">App is loading!</p>
</div>
</div>
<div id="appWrapper" ng-controller="appCtrl">
...
</div>
<!-- All stylesheet includes -->
...
<!-- All script includes -->
...
<script src="/.../hideLoadingScreen.js"></script>
<hide-loading-screen></hide-loading-screen>
</body>
</html>
And the hideLoadingScreen directive:
(function() {
var app = angular.module('appModule');
app.directive('hideLoadingScreen', function($timeout) {
return {
restrict: 'E',
link: function() {
$timeout(function() {
$("#appLoadingScreen").fadeOut(600, function(){$(this).remove();});
}, 400);
}
};
});
})();
回答6:
While @chotesah answer is just right I can suggest you go another way and use preloaders for each image (something like Facebook on page load).
Try this module. You'll need to change few lines:
// Add module dependency
angular.module('app', ['angular-preload-image']);
…
<img preload-image idx="id-thumb-{{$index}}" ng-src="/imagedisplay/{{image.imageid}}" default-image="[URL]" fallback-image="[URL]" />
After that look for nifty image preloaders at codrops.
来源:https://stackoverflow.com/questions/33030360/angularjs-how-to-show-preload-or-loading-until-page-is-loaded-completely