What modules / tips can be used to handle loading in AngularJS? Basically, how do you include a loading icon when a page is being loaded (for instance account settings of the user OR when the page is initially loaded)? Is there a standard procedure or ng- module?
Ps. If my question is too vague or inappropriate, please correct me. I do think that it has crossed the minds of most Angular beginners.
This is by far the easiest method of indicating one or multiple XHR requests in progress, if you're using a flavour of ui-routing, it'l also show you the HTML files being fetched in XHR requests.
http://chieffancypants.github.io/angular-loading-bar/
It's a bar that looks the same like the Youtube loading indicator, and it's easily style-able.
Just include the library as an ng-module, that's it.
angular.module('myApp', ['angular-loading-bar'])
You might want to disable either the circle or the bar itself(both at the same time might look a bit too much).
I found this answer to be very helpful, courtesy of Josh David Miller:
.controller('MainCtrl', function ( $scope, myService ) {
$scope.loading = true;
myService.get().then( function ( response ) {
$scope.items = response.data;
}, function ( response ) {
// TODO: handle the error somehow
}).finally(function() {
// called no matter success or failure
$scope.loading = false;
});
});
<div class="spinner" ng-show="loading"></div>
<div ng-repeat="item in items>{{item.name}}</div>
Source:
https://stackoverflow.com/a/15033322/4040107
had answered similar question earlier as well.... If you dont want to implement it yourself, below are few links.
angular-spinner or angular-sham-spinner
also read this BLOG which details how the spinner works with angularjs
if you want to implement it yourself... then
app.directive("spinner", function(){
return: {
restrict: 'E',
scope: {enable:"="},
template: <div class="spinner" ng-show="enable"><img src="content/spinner.gif"></div>
}
});
i havent tested the code but directive wont be more complex than this...
Related
Apologies if the question isn't correctly worded, but here it goes: I currently have a website which needs to display a certain image, however, the link provided to me is a link that redirects to the image.
So think www.linktoimage.com/foo, which redirects me to my actual image's url, so for example, https://i.imgur.com/76lLZAn.png.
Unfortunately this is a requirement to the project I am working on for several reasons and I can't really think of a way to get around this.
For the record, I am using meteor with the blaze template engine, in case that helps. A way I thought of getting this done may be through using a helper, which will follow the redirect for me, and somehow grab the ultimate url. So something like this:
Template.myTemplate.helpers({
getMyImage: function (proxyUrl) {
var actualAddress
// somehow get the images actual address...
return actualAddress
}
})
Then in my html file:
<template name="myTemplate">
<div>
<img src="{{getMyImage 'proxyUrl'}}"
<div>
</template>
Of course if there is a better way to do this just through the HTML that would be fantastic too. Unfortunately right now, I am clueless on how I would get the actual URL.
Thanks!
Edit: essentially I want to do this, but using JavaScript instead of PHP.
Edit2: possibly found a way to get around this, though it is not quite working and has some problems due to it being async. Basically it would be using meteor's HTTP library:
Template.myTemplate.helpers({
getMyImage: function () {
var proxyUrl = 'http://www.tablotv.com/client-paywall-snapshots/web'
return HTTP.call('GET', proxyUrl, function (err, result){
console.warn('hereeee', result, err)
})
}
})
However I am getting the following error:
network at XMLHttpRequest.xhr.onreadystatechange
I can imagine this has something to do with it being async, perhaps? Anyway, am I on the right path now? How could I get this working?
I have a current project based around single-page-applications (SPA) and wanted to implent a function that dynamically loads directives into my html based on which kind of SPA is required.
The relevant code for that is:
the part of my controller that should load the directive
function checkSpaType(x) {
if (x === "quiz") {
const directivePosition = document.getElementById("spa");
directivePosition.append($compile("<quizSPA></quizSPA>")($scope));
};
};
the directive itself
function quizDirective () {
return {
templateUrl: "templates/quizSPA.html",
controller: 'quizCtrl',
link: function quizSPA() {}
}
}
and of course it doesnt work as planned.
After I run the scripts the only thing that gets loaded in my HTML is the message
"[object HTMLUnknownElement]]"
iam very sure that angular just cant find my directive, but how do I make it visible to it?
Also the template folder is in the same folder as my index.html from where the site starts. So that shouldnt be a problem. Likewise I already tried renaming the tags I load the in the html, sadly to no effect.
Anyone has an idea?
I fixed it myself right now.
Had to change:
directivePosition.append($compile("<quiz-s-p-a></quiz-s-p-a>")($scope))
to:
const spaDirective = $compile("<quiz>")($scope);
directivePosition.append(spaDirective[0]);
Sometimes in my application a HTTP call to get a list or some sort of resource will fail for no obvious reason, however, if it's re-fired straight away it will work.
Is there a way to configure all HTTP calls to say something along the lines of
if ( has no success after 2-3 seconds ) {
re-fire HTTP call...
}
I find in my application (which is ASP.NET) that often times I have to double click a link to make a page load. This I feel is probably the same issue with the HTTP calls in the code. Not sure as to how to trace or de-bug this sort of problem and if anyone had any thoughts on that you would really be helping me out!
Any advice much would be greatly appreciated.
Thanks!
you can do it using an $httpInterceptor, maybe a god solution could be fix the problem instead of that, by the way, there is an example:
this wonderful post maybe help you to understand $http interceptors
(function(window, angular, APP) {
var MAX_ERRORS = 1; // after that: giving up
function FeelAgainConfig($httpProvider) {
$httpProvider.interceptors.push(function FeelAgainInterceptor($q, $http) {
var interceptors = {};
interceptors.responseError = function FeelAgainInterceptorResponseError(data) {
// implement an error counter that helps you to not fall in an infinite call stack
if(data.errorCount >= MAX_ERRORS) {
return $q.reject(data);
};
// Perform the request again;
};
return interceptors;
});
}
APP
.config(FeelAgainConfig)
;
})(window, window.angular, window.angular.module('feelAgain$http', []));
If you're looking to change the behaviour of the $http service in Angular, then there is a way. This post describes it briefly, and here's the important bits citated from the post.:
For example if you are making a late global alteration to a large
ongoing project, or want to change the behavior of XHR requests in
third party code that can't be altered. In these circumstances you
might use $provide.decorator() to globally replace $http with a
wrapped version.
By wrapping the $http servie you have the option to change behaviour.
It sounds like you have a different problem though since you need to trigger calls twice, I suggest you solve that first.
in my app I would like to add functionality to translate page into all languages that user has set in browser and if none of them is available translate into default english... Problem is browser inconsistency with language support. I found a workaround for this, I make a http call to some webservice which returns user languages. It is done in app.run
app.run(function($rootScope, UserDataService, $translate){
UserDataService.getUserBrowserLanguage().then(function(language){
var langArr = language.split(',').map(function(el){
return el.split(';')[0].split(/-|_/)[0];
});
$translate.fallbackLanguage(langArr)
$translate.preferredLanguage(langArr[0]);
$translate.use(langArr[0]);
});
});
and in app config:
app.config(function ($routeProvider, $translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: '/languages/',
suffix: '.json'
});
});
section because I can't make http call in config and it fails... :/ langauges are loaded but the translation isn't changed... What am I doing wrong? Here is plunker:
http://plnkr.co/edit/41SngK2tCTeaq8IhMbcM
it doesn't display anything no translations... why? :( I would be very pleased with any help.
As for your question the view doesn't show anything due to the following errors:
Few mistakes:
First of all, ng-app should be moved to the html tag.
<html ng-app="translateApp">
Second, if you use a variable from a controller you should use ng-controller.
<div ng-controller="mainCtrl">
Last, when you bind a variable from the view to the controller the variable should be on the $scope.
$scope.translation = $translate.instant('GENERAL');
Fixed your plunker with my comments: Plunker.
As for the way $translate works, I am not really familiar with this service but I will try and have a look.
EDIT:
I studied $translate service in order to give you a full answer including fixing the way you used Translate, So first of all I put a timeout of 2 seconds before trying to use translate.instant, the reason is that I am letting translate loading the JSON files in the config.
I have added 2 buttons so you could switch between the languages and see it is working.
Enjoy! Here is the updated working Plunker.
Here is translate documentation site I used.
I'm trying to use the Angular-UI TinyMCE directive in my Angular app.
What happens is, I query an endpoint, it returns an array of objects. I have a function that then converts that to a long string with HTML tags in it. Then that data is set to a $scope.tinymceModel
This all works fine. I can console.log($scope.tinymceModel) and its the proper data.
The problem is the HTML parse function needs to run after the endpoint query is returned. So I've called the function inside the .success() callback. For some reason when I set the $scope.tinymceModel inside of the callback the TinyMCE directive ignores it. Even if I make it $scope.tinymceModel = 'test' but if I place $scope.tinymceModel = 'test' outside of the callback it shows up in tinymce just fine.
This tells me that for some reason when the TinyMCE directive is loaded it needs the tinymceModel to already be populated with data. I'm not sure how I get around this.
This also tells me that I may have another problem after this. The next task with TinyMCE is the user can then edit the text, click a button and the app will send a POST with the updated info inside tinymceModel If this was a regular text box it would be simple because of the data-binding. However it seems TinyMCE doesn't play well with databinding.
Any ideas?
I've attempted to recreate what you're describing (substituting $http with $timeout) to no avail. Here's my solution and it seems to be working just fine.
HTML:
<div ng-controller="MainCtrl">
<textarea ui-tinymce="" class="form-control" ng-model="someHtml"></textarea>
</div>
JavaScript:
angular.module('testTinymceApp')
.controller('MainCtrl', function ($scope, $timeout) {
$timeout(function() {
$scope.someHtml = '<h1>HELLO THERE</h1>'
}, 7000);
// This does the same thing with an XHR request instead of timeout
// $http.get('/some/data/').success(function(result) {
// $scope.someHtml = '<h1>HELLO THERE</h1>'
// });
});
I thought maybe you could compare with your own application? I know for a fact that this works with XHR requests. I'm building a CMS at work that uses what I assume is an identical workflow.
The someHtml attribute in this snippet will also be valid HTML under the covers, so sending it back in a POST request should be extremely easy.
If this is not sufficient, please provide further explanation.
Figured it out!, the issue has to do with a bug in the TinyMCE Directive. By default there is no priority set. Setting it to a value of 1 or higher fixes it. It seems that the current version of Ui-TinyMCE Directive has this fixed, but the version I pulled down less than a month ago didn't have it fixed.