AngularJS show loader on every page - angularjs

I am trying to make a loader that will show on every page and fade out when all the content is loaded. Here is my code so far:
<div id="loader-wrapper" data-loader-drct data-ng-hide="hidden">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
</div><!--end loader-wrapper-->
app.directive('loaderDrct', [function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$on('$routeChangeSuccess', function () {
var hide = false;
scope.hidden = hide;
scope.$on('$viewContentLoaded', function () {
hide = true;
scope.hidden = hide;
});
});
}
}
}]);
When I execute this code, the loader is hiding (with some CSS added), but when I go to another page, the loader is not shown again. The ng-hide class is still there, which means that this directive has already been executed and did not refresh after going to the new page.
How can I make the loader show and hide on every page?

ok, I found a solution made by michael. The problem is that the templates are loaded and the browser has no time to make the changes visible . You can find the full answer here: Angular js - show/hide loading gif every new route

For load while upload/download files
Add in index.html
<div id="loading_wrapper">
<i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
</div>
And Add in controller.js
var $loadingWrapper = angular.element('#loading_wrapper');
Note: Make sure whether font-awesome css files installed or not. Otherwise, you can use simply bootstrap components.

Related

Angular Anchor Scroll without Promise

I have am trying to use a very simple scrollTo in Angular 1.x. I have naviagation menu link which when clicked should scroll to a div#id. I can only get this to work with a 'promise'.
For example, this works:
<li>Go to Tracking</li>
$scope.tracking = function() { // go to tracking when header button is clicked
$http.get('/includes/modules/get_home_destinations.php')
.then(function(reply){
if (reply.data) {
$scope.destinations = reply.data;
$location.hash('home-tracking');
}
});
};
But this doesn't respond:
$scope.tracking = function() { // go to tracking when header button is clicked
$location.hash('home-tracking');
};
It's as if a promise is required, but to get this to work on the simple click without the promise?
This is because of href="#" as I guess. Because firstly, href redirects page to "#" then the promise is executed with time delay and redirect back page to the desired location. But without promises, there is no time delay, code is executed immediately and href redirects page to '#' and page stuck there.
Hope this below code will be usefull :
in html file
<div id="home-tracking">
<h1>Home Traking Content</h1>
</div>
<a ng-click="tracking()">Go to Tracking</a>
in controller file
angular.module('trackingApp').controller('TrackingCtrl', function($location, $anchorScroll) {
$scope.tracking = function() {
$location.hash('home-tracking');
$anchorScroll();
}
})

Angular: ng-bind-html removing ng directives from HTML data fetched from Firebase

I am saving data in firebase from WYSIWYG editor using angularJS. This data will be in HTML format.
I am fetching HTML data from firebase and with the help of angular directive ng-bind-html this HTML content is sanitized and text saved on the editor will be shown to the user. This text could contain text, images, links.
<div ng-bind-html="newHTML" ng-model="cleanText1"></div>
The HTML coming for data with link is in the below format:
<p>This is text editor link<br></p>
Now if I click this link on the page it will redirect to the URL specified.But I want this link to open the page in a div which is to the right hand side of the page.
To prevent this behavior I replaced href with ng-href using code below:
$scope.newHtml=$scope.htmlcontent1.replace("href","ng-href");
$scope.newHTML=$sce.trustAsHTML($scope.newHtml);
Doing this ng-bind-html removed ng-href
<p>This is text editor <a>link</a><br></p> Which made it unclickable.
Also I have tried to add directive for a tag so that once user clicks this link I can give my own functionality instead of redirecting the user.
Directive looks like this:
app.directive('a', function ($compile) {
return {
restrict: 'AE',
link: function (scope, elem, attrs) {
var href = elem.children('a').attr('href');
console.log("href"+href);
elem.children('a').attr('href', null);
elem.children('a').attr('ng-click', 'open()');
$compile(elem.contents())(scope);
console.log("elem"+elem.children('a').attr('href'));
scope.open = function () {
alert('1');
}
}
}
})
But directive is being called once the user clicks and is redirected to the new page.
Any ideas how to make this link open in right hand side of the page?
Appreciate your help.
Let's make some tweaks in your code to get it in action.
Try this instead.
Make your own directive for sanitizing HTML in place of using ng-bind-html.
Replace
<div ng-bind-html="newHTML" ng-model="cleanText1"></div>
To
<div cleanHtml="newHTML" ng-model="cleanText1"></div>
cleanHTML will be a customized directive.
Make below directive in app.js to render HTML content.
app.directive('cleanHTML',['$compile',function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compile);
},
function(value) {
console.log(value)
// Here you can see your HTML is going to get sanitized below
element.html(value);
$compile(element.contents())(scope); // After this HTML will be sanitized.
}
)};
}])
Next is to suppress the behavior of href and apply a click function on the link so as to define your own functionality for the link.
Now replace this:
$scope.newHtml=$scope.htmlcontent1.replace("href","ng-href");
$scope.newHTML=$sce.trustAsHTML($scope.newHtml)
To
$scope.newHtml=$scope.htmlcontent1.replace
("<a ","<a ng-click=\"$event.preventDefault();open()\"");
$scope.open = function()
{
alert("Whoa! It worked :)");
//Write your code here
}
This replacement will add ng-click to Link.
For e.g. if your HTML is like this
link
It will become like this
<a ng-click="$event.preventDefault();open()" href="http://someLink">link</a>
$event.preventDefault() has been added to override href functionality so that ng-click functionality takes priority.
Now once you are able to make your link working after that comes the display part which is now a piece of cake.
You want that on click of that link content appears to the right hand side of the page.
You can fetch the content of the link and add in scope variable like this:
$scope.newHtml=$scope.htmlcontent1.replace("<a ","<a ng-click=\"$event.preventDefault();open()\"");
$scope.open = function()
{
alert("Whoa! It worked :)");
//Write your code here
//fetch the content in var content
$scope.linkContent= content;
}
use linkContent and add it to the right hand side of the DIV of HTML page where you want to display and it's done :)
<div>{{linkContent}}</div>
Hope it works.
Happy Coding !!!

AngularGrid doesn't load when refresh page

I'm using this AngularGrid system and everything is working so far, except when i refresh the page.
In the doc there is an orientation on how to solve this:
To get the reference of instance you need to define angular-grid-id on the element which you can get back by injecting angularGridInstance to any controller or directive. Using your id you can refresh your layout ex : angularGridInstance.gallery.refresh();
And this is what I did:
html
<ul class="dynamic-grid" angular-grid="pics" angular-grid-id="mypics" grid-width="300" gutter-size="10" refresh-on-img-load="false" >
<li data-ng-repeat="port in Portfolio" class="grid" data-ng-clock>
<img src="{{port.img[0]}}" class="grid-img" />
</li>
</ul>
app.js
.directive('myPortfolio', ['mainFactory','angularGridInstance', function (mainFactory,angularGridInstance) {
return {
restrict: "A",
link: function($scope) {
mainFactory.getPortfolio().then(function(data) {
$scope.refresh = function(){
angularGridInstance.mypics.refresh();
}
$scope.pagedPortfolio = data.data;
})
}
}
}])
But if I refresh the page, it still doesn't work. There is some boxes but without image loaded and it's not inside the grid system. Also, I have no errors in my console. When this happens, I can only see the images again if I change to another page and then go back to my portfolio page.
Any ideas on how to solve this?
I think you don't need angularGridInstance and refresh function here. Just change
refresh-on-img-load="false"
to
refresh-on-img-load="true"
in your view.

Is there any way to delay ng-view?

I have layout where I have:
<li ng-click="GetLoader();">ACCOUNT</li>
<li ng-click="GetLoader();">SETTINGS</li>
On the index page, I have a menu and ng-view where I can change pages on a click
Also included on the index page is a spinner.
<div class="loading" ng-show="ticketloading" ng-init="GetLoader()">
<div>
<img class="spinner" ng-src="~/Images/ajax-loader.gif" />
</div>
</div>
In my script I have -
$scope.GetLoader = function() {
$scope.ticketloading = true;
loader.css("z-index", "1");
}
My problem is that when a user clicks on "Account" it gets loaded, but just for few milliseconds. Then it changes to all blank. I receive data from ng-view. My question is how can I delay showing ng-view to show the loader a little bit longer.
Thanx in advance!
First of all you should avoid using DOM manipulations in controller. In your case it's better to use declarative ngClass directive to set opacity.
Then your actual issue is that you don't want to use static setTimeout to hide loaded, but rather listen $routeChangeSuccess:
$rootScope.$on('$routeChangeSuccess', function() {
$rootScope.ticketloading = false;
});
and use this loading flag in template like you are currently doing.
You can put above event listener in run block for example.
You can add property in your controller, for example dataLoading and add ng-if attribute to ng-view like this:
layout
<div ng-view ng-if="!dataLoading">
controller
function loadData()
{
var self = this;
self.dataLoading = true;
dataService.loadData(params, function(){
...
self.dataLoading = false;
});
}

Elegant burger menu directive

I have started to develop a burger module, consisting essentially in 2 parts :
a "burger-opener" button which opens the menu, most probably an attribute directive including a click event listener, dom and css agnostic
a "burger menu" element, most probably a directive benefiting from transclusion, letting the client decide what the menu contains for the sake of reusability. This basically provides a close button at the top of it, before the ng-transclude element.
There must be a tight relationship between those 2 elements in terms of functionality, i.e the button element will call "open" into the burger menu element.
The thing is, I have a constraint which is that the button and the menu do not have to be contained within each other. For example, one must be able to use the module like so
<ul burger-menu>
<li>Save</li>
<li>Load</li>
</ul>
<section id="container">
<a href="" burger-opener class="burgerOpen"><a>
</section>
This constraint seems to be auto-excluding directive to directive communication using the "require" syntax because this angularjs functionality supposes directives are self-contained. So unless I create a top level DOM controller containing my 2 elements... I'm stuck.
I have been using a brute force approach, that is to use a broadcast from the rootscope for the button to send the "open" message to the menu directive. It works like a charm but I am not satisfied with it.
One other approach would be to set an even on the button but I would take this as a failure for some weird reason. I'm probably wrong but I'm quite sure there is a more elegant way to connect those two elements using the AngularJS paradigm without using broadcast nor events.
Do you know it ? I guess basically I am asking how components such as ui bootstrap modal service actually work.
Here is what I came up to. This seems quick and reusable enough to me, let me know if you can create something better !
Basically, the burgerMenu directive shares its parent scope (scope:false or nothing, it's false by default) and sets an api within it using the 'controller as' syntax. Thus the button whose role is to open the menu has a clear click handler with burgerCtrl.openBurger().
Here is the burgerMenu directive :
angular.module('app')
.directive("burgerMenu", [function () {
return {
scope: false,
controller: function () {
var self = this;
this.openBurger = function () {
self.isOpen = true;
};
this.closeBurger = function () {
self.isOpen = false;
};
this.isOpen = false;
},
controllerAs: 'burgerCtrl',
restrict: 'E',
replace: true,
transclude: true,
templateUrl: 'js/app/burgerMenu/_burger.tpl.html'
}
}
]);
The template :
<section class="nav_bar" ng-class="{open:burgerCtrl.isOpen}">
<div class="nav_content" ng-show="burgerCtrl.isOpen">
<h1 ng-click="burgerCtrl.closeBurger();">X</h1>
<ng-transclude></ng-transclude>
</div>
</section>
Css (main idea) :
.nav_bar { position:fixed; }
.nav_bar.open { width: 240px; }
Usage :
<section id="header">
<div class="burger" ng-click="burgerCtrl.openBurger()"></div>
<h1>App title</h1>
</section>
<section data-burger-menu>
<ul id="menu">
<li>Save</li>
<li>Share</li>
<li>Load n°1</li>
</ul>
</section>

Resources