Angular directive gets "Synchronous XMLHttpRequest on the main thread is deprecated" - javascript

I have an Angular directive element nested inside a controller, and I get this message
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
WARNING: Tried to load angular more than once.
I kinda understand what it means, but I don't know what is causing this issue. Here's what I have:
audio.html
<div class="audio-top-bar" ng-controller="AudioController">
<div class="audio-tuner-button" ng-click="displayTunerModal()">
<button class="btn">
<p class="audio-tuner-type">{{tunerButton}}</p>
</button>
</div>
<display-tuner-modal ng-show="visibility"></display-tuner-modal>
</div>
AudioController.js
angular.module('app').controller('AudioController', ['$scope', 'TunerService', function($scope, TunerService){
$scope.visibility = false;
if ($scope.tunerButton == (null || undefined))
$scope.tunerButton = 'FM';
$scope.displayTunerModal = function(){
$scope.visibility = true;
};
}]);
displayTunerModal.js
angular.module('app').directive('displayTunerModal', ['TunerService' , function (TunerService){
return {
restrict: 'E',
link: function(scope, elem, attrs){
scope.displayTunerModal = function(){
console.log("CLICKED");
};
},
templateUrl: 'public/templates/displayScreenModal.html'
};
}]);

My apologies the problem was as simple as having an incorrect name for the link within the directive. I should have had "displayTunerModal.html".
Moral of the story: check your links.

As per this question I had the same Synchronous XMLHttpRequest on the main thread is deprecated in an AngularJS directive on my production server while having no such error on my local environment.
In my case this was due to a case mismatch in template name vs js request :
AngularJS (a directive in my situation) was requesting lowercase mytemplate.tmpl.html
the template file was named with camelCase: myTemplate.tmpl.html
What confused the issue was that the directive / template worked fine on the Mac (due to OSX case-insensitivity) - but failed when pushed to a Linux case-sensitive AWS production server.
Changing the template file name to lowercase fixed the issue.
As mentioned in one of the comments above, the AJAX error is misleading as it implies something wrong with a specific call, rather than simply that a file is "missing".

Related

Allow skype calls from Angular App (using meanjs)

I can not get rid of a small issue affecting my app functionality to enable to call a phone number using skype, what I have so far is this:
HTML:
<a ng-href="skype:{{user.phone}}?call" class="btn btn-sm btn-success" type="button">{{user.phone}}</a>
ANGULAR
(function() {
angular.module('core').config(coreConfig);
coreConfig.$inject = ['$compileProvider'];
function coreConfig($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|tel|file|skype):/);
}
})();
The result is always the same, when I hover the element to start a call the browser show this: unsafe:skype:012345678?call and do not allow me to call the number...
I added the config part browsing other questions related to similar issues but it doesn't solve my issue.
EDIT:
I'm using meanjs.org
EDIT 2:
Please do not copy/paste my question code as your answer... I know that it work on a normal Angular application. The problem is that I can not let it work using meanjs.org app. Thanks.
EDIT 3:
I just found that: if I use the skype link in the main root / or in a child root like: /list it work fine without adding the unsafe prefix. In a dynamic root like: /list/1234 it doesn't work anymore. I don't know if it could help.
The "bug" was caused by an old version of ngFileUpload that overwrite my configuration as reported here.
Upgrading the version of ngFileUpload solved my issue.
Thanks for your help.
You need to explicitly add URL protocols to Angular's whitelist using a regular expression. Only http, https, ftp and mailto are enabled by default. Angular will prefix a non-whitelisted URL with unsafe: when using a protocol such as chrome-extension:.
A good place to whitelist the chrome-extension: protocol would be in your module's config block:
var app = angular.module( 'myApp', [] )
.config( [
'$compileProvider',
function( $compileProvider )
{
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension):/);
// Angular before v1.2 uses $compileProvider.urlSanitizationWhitelist(...)
}
]);
The same procedure also applies when you need to use protocols such as file: and tel:.
Please see the AngularJS $compileProvider API documentation for more info.
I've made it work in following plunker
http://plnkr.co/edit/rIPFz9WhFjlRJ1ogCArP?p=preview
angular.module('plunker', [])
.config(function($compileProvider){
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|skype|mailto|tel|file):/)
})
.controller('MainCtrl', function($scope) {
$scope.href = 'skype:123456?call';
});

Angular code stops working when it's moved to a template file

I'm new to Angular, so the documentation is a bit of a bear. When I created the following code, and it worked, I thought I was in a good place.
<div ng-controller="postListController">
{{someDataStuff}} <!-- this always works -->
<div ng-repeat="post in data">
<b>{{post.title}}</b> <!-- This sometimes works -->
</div>
</div>
...and this Javascript in Angular (a snippet, really)
var listController = app.controller('postListController', function postListController($scope) {
$scope.someDataStuff = 'hey there.';
$scope.data = new Object(null);
$.get('get.php',function(data) {
$scope.data = JSON.parse(data);
console.log($scope.data);
});
});
someDataStuff printed out, and Angular looped happily through the post.titles. Then I tried moving this stuff, verbatim, to a template file and loading it appropriately...
app.directive('ngPostList', function() {
return{
restrict: 'E',
templateUrl: 'postlist.html'
}
});
This part... only sorta worked. While I was still getting data (returned it in console.log), and I was still getting someDataStuff to come back, it was no actually looping through the data.
Is there something in app.directive I'm missing to make it pass data on to the template I'm now using?
Your template should also take the controller, otherwise it is outside the scope and you are one level further down and you would have to call $parent.post.title etc... to reach the proper parent scope with the data.
try:
app.directive('ngPostList', function() {
return{
restrict: 'E',
Controller: 'postListController',
templateUrl: 'postlist.html'
}
});
Overall, pick up one of the Chrome extensions to debug Angular, like ng-inspector, so you can see what scope has what data and it makes your life a lot easier to debug this kind of things.
Angular issues are 95% of the time issues with scope not being what your think it is.

Javascript \ Angular function help - mental block

I don't know what it is about JS, but I have a mental block. I apologize for the dumb question, but I'm at a loss because no matter how much I read I cannot get the academics into practice. Especially when it comes to nested functions.
I have a controller, lets say FileCtrl. Inside of it I have the the following that listens for file added to an input field via a directive. I'm attempting to inject an Angular JS factory service service called fileReader (a queue service for HTML5 FileReader).
However,I keep getting a undefined error on fileReader. I know why because, it cannot see fileReader, but injecting it at $scope.$on and then again on $scope.$apply doesn't work. Also, adding fileReader as a closure at the end of $scope.$on doesn't work either.
I should add that I can see the args.file and if I remove the fileReader code it will push the file no problem, but I then have no thumbnail. So I it works, just not with the fileReader and that is because Im doing something wrong with injection.
Side note, to Vals comment below I use apply as I found there was a image render sync issue without it which works fine for smaller images, but with larger images it freezes which is why I'm attempting to create and use a $q fileReader service. I suppose another way to solve for it would be to create a watch / directive on the array entry and when img comes back with the 64 encode string populate the html element ... like I said JS mental block :)
myApp.controller('FileController', ['$scope', 'FileReaderService', function($scope, FileReaderService ){
$scope.$on("fileSelected", function (event, args) {
$scope.$apply(function () {
$scope.progress = 0;
fileReader.readAsDataUrl(args.file, $scope)
.then(function(result) {
$scope.imageSrc = result;
});
$scope.files.push(args.file);
});
});
});
In AngularJS not all functions are been processed by Dependency Injection. In Controllers, Directives (in definition of directive and in controller, not on link or compile), Servicies AngularJS inject requested instances, but in some other functions (like event listeners) arguments are passed by position.
In your case you need to put fileReader into definition on controller, not on event listener.
Also you need to remove apply because event listeners added via $on are included into digest loop.
Thanks to all for your replies. Val you made me go back and do a little more research and I found the answer with a little debugging. Not sure I understand why yet, but I have an idea.
If there is an error in your factory service, in my case, FileReaderService angular won't always explode when bootstrapping the service, will only explode when you call the service, which makes kind of makes sense. If something is wrong in the service the entire service will not boot. Also, you won't get any error message when injecting it into the controller. I had to place a watch on the module and noticed there was a reference error. I found I had a missing function.
Purely inexperience on my end, but I kept trying to capture the results form the $q service, which is was doing fine, but then attempting to inject to outside the $q return i.e. I was attempting to capture $scope.imageSrc = result and insert it post the .then, which doesn't work as you have a sync issue. I could see the value in the $scope.files, but it would not console.log or show up in HTML. So I moved all the file manipulation into the .then and it works perfectly. Logical when you think about it :) why have a $q if you not going to use it ... lol.
// problem code
fileReader.readAsDataUrl(args.file, $scope)
.then(function(result) {
$scope.imageSrc = result;
});
// cannot and should not try to work the results outside the return promise
$scope.files.imgSource = $scope.imageSrc;
$scope.files.push(args.file);
//Fixed and working code
myApp.controller('FileController', ['$scope', 'FileReaderService', function($scope, FileReaderService ){
var reader;
$scope.files = [];
//listen for the file selected event
$scope.$on("fileSelected", function (event, args) {
$scope.progress = 0;
var file = args.file;
FileReaderService.readAsDataUrl(file, $scope)
.then(function(result) {
file.imgSource = result;
$scope.files.push(file);
});
});
});

What *is* the ngModel.$validators pipeline?

While performing some basic research on custom client-side validation in Angular.js, I was reading the ngModel.NgModelController documentation, and found the following cryptic line:
$setValidity(validationErrorKey, isValid);
Change the validity state, and notifies the form.
This method can be called within $parsers/$formatters. However, if possible, please use the ngModel.$validators pipeline which is designed to call this method automatically.
A couple of hours and many Google (and StackOverflow!) searches later, I have found nothing about this ngModel.$validators pipeline anywhere. All custom validation examples use the $parsers/$formatters setup as below:
link: function (scope, elem, attr, ctrl) {
// Other necessary logic...
ctrl.$parsers.push(function () {
// Validation logic
ctrl.$setValidity('validation-type', true);
});
ctrl.$formatters.push(function () {
// Validation logic
ctrl.$setValidity('validation-type', true);
});
},
Question: The Angular documentation states that the above code is not the best practice, and that this mythical ngModel.$validators pipline is the correct way to go. I have failed to find any information on this better practice. How does one use ngModel.$validators to correctly implement this custom clientside validation?
$validators are new to Angular 1.3. This blog post gives a good explanation on how to use them: http://www.yearofmoo.com/2014/09/taming-forms-in-angularjs-1-3.html#the-validators-pipeline
The basic idea is that you add a function onto ngModel.$validators that returns a boolean specifying whether the model is valid.
Then you can refrence that validator in your HTML the same way you would reference any built in validators. e.g.
<div ng-if="myForm.myField.$error.myValidator">
some error message here
</div>

In Angular: are the compile function's pre and post methods the same as link's pre and post

In an angular directive's compile function there is a pre and post. Is this pre and post really the same as the link function?
For example in the code below, is the link function the same (shortcut if you will) as the pre and post of the compile function below it?
Link
....
link: {
pre: function(scope, elem, attr) {
//stuff
},
post: function(scope, elem, attr) {
//stuff
}
}
....
Compile...
....
compile: function(tElem, tAttrs){
return {
pre: function(scope, iElem, iAttrs){
//stuff
},
post: function(scope, iElem, iAttrs){
//stuff
}
}
}
.....
Compile is run first (and is usually where you maipulate your "template" dom elements). Link is run second, and is usually where you attach your directive to $scope.
They also run in a specific order, so you can use that fact when you're designing directives that require some "parent" directive setup in order to operate properly (like a tr:td sorta thing).
There's a really great article on timing for compile vs link you can take a look at for more clarity.
Also - there's a very low level stack answer to a similar question you might like (note that its NOT the one listed first, it's the one most upvoted).
So, What's the Difference?
So are compile pre/post link "the same" as the link function? You decide.
If you define compile on a directive, the framework ignores your link function (because the compile function is supposed to return pre/post link functions).
It's a little bit like link overloads compile.postLink and link.pre overloads compile.preLink.
When this overloading happens, are you aware of anything different happening (i.e. any other functionality being added) as supposed to just returning pre and post from compile?
If you look at the source code,
when the $directiveProvider registers the directives, if the compile property is missing and the link property exists, it creates a compile property that is an empty function that returns the link property.
So the answer is that the link functions returned by the compile function are the same as the link functions provided by the link property of the DDO. No other functionality is added.

Categories

Resources