I know it is not a good practice to use Angular services outside of angular but nevertheless it's very interesting for me, for example I have
.constant('APIprefix','/api')
how can I retrieve APIprefix value outside of angular scope? For instance from other js file which is not in angular scope.
You can access any service like this:
angular.element(document.documentElement).injector().get('APIprefix');
Note that you should pass to angular.element DOM node where you put ng-app. In the example above document.documentElement is HTML tag.
Demo: http://plnkr.co/edit/nf8zhDsl1PAnE5zDYYaG?p=preview
pixelbits example did not worked for me. I needed to do a small change to do it.
Writting constants
var app = angular.module('module',[]);
app.constant('APIprefix', '/api');
Reading from non angular scope
var prefix = angular.injector(['ng', 'module']).get('APIprefix');
Thanks pixelbits for showing me the way :)
Related
I need to call a function defined in a component of my AngularJS 1.6 app but i need to do this in simple javascript code outside the angular app. How can I do this?
If you want to test something quick and dirty, the function can be accessed from the Developer Console with:
scope = angular.element($0).isolateScope();
scope.$ctrl.myFunction();
Where $0 is set by selecting the component by using right click -> Inspect or clicking the element in the element window of the Developer Console.
For more information, see AngularJS angular.element API Reference - jQuery/jqLite Extras
Using a standard event-broadcasting will help you.
Inside your component:
document.addEventListener('trigger-my-method', () => myMethod());
Somewhere else:
let myEvt = new Event('trigger-my-method');
document.dispatchEvent(myEvt)
Edit:
I'm not tested this solution, and i'm not deep into angular, but it should work
I am having a little trouble hiding an element. I am attempting to hide this element using an AngularJS service. My code is as follows:
app.service('testService', function(){
var testElement = $("#testElement");
this.hideElement = function(){
testElement.hide();
}
});
The code above does not actually hide the element, but the following code does:
app.service('testService', function(){
this.hideElement = function(){
var testElement = $("#testElement");
testElement.hide();
}
});
However, I have multiple functions that use the testElement and I would hate to have to keep declaring it in all the functions that need testElement within the service. Am I doing something wrong here?
Am I doing something wrong here?
Yes. In fact your very first step was wrong. I mean having service that makes some DOM manipulations, in your case hiding HTML node. Services are data manipulation layer (retrieve, transform, save, post, etc.) but never presentation one, it should not care about View. Services are reusable piece of application code, meaning that it is supposed to be injected in different places of the app to provide a bridge to data sources, it should not make any view transformations, it's just not what they are for.
You should use directive for this with controller as mediator to decide when and what to hide and show. Most likely it will be enough to use build-in ngShow/ngHide directives with some boolean flags set in controller.
for html manipulation better to use angular controllers or inbuilt directives. services are never recommended.
If you really want to cache something, use simple JS Constants or html5 localstorage if you cache session wise use sessionstorage, they are really helpfull. or in angular $rootscope variables are also global.
Yes. What actually happened when you assign 'testElement' outside the hide method was 'testElement' will be assigned with undefined value.Since injection are created before the dom was available.So the below code doesn't work.
var testElement = $("#testElement");
this.hideElement = function(){
testElement.hide();
}
For DOM manipulation it is better to go with directives than services.
In my application, I need to be able to easily determine whether a user is authenticated within my HTML and in all templates.
My first thought on how to do this was to create a "global" controller and apply it to which simply set $scope.isAuthenticated = $auth.isAuthenticated.
However, after doing some reading, I discovered that this wasn't considered good practice. Instead, I created a directive, which would just return $auth.isAuthenticated().
angular.module('HordeWebClient')
.directive('isAuthenticated', function($auth) {
return $auth.isAuthenticated();
});
And then in my templates, I figured I could just use .... This doesn't work, the element isn't rendered regardless of the state of $auth.isAuthenticated.
The Safari error console doesn't show any problems, so I'm stuck on where to start in fixing this. Any pointers would be greatly appreciated.
In my opinion you should use .run on your main module.
angular.module('app').run(function(){
if(!isAuthenticated){
redirectToLoginView();
}
});
More: https://docs.angularjs.org/guide/module
I'm trying to make a blurred background efect with angular on a div, something like the image above, for this i'm using blur.js and everything work fine with jquery but the real question is this posible with angularjs, and what is the best way?
I'm really newbie with angular
thanks in advance
here another example of using blurjs http://www.designedbyaturtle.co.uk/2013/blur-a-background-image/
SOLVED (with help of gtramontina):
you can download the code here demo-blurjs-angular
The result (with my images)
This demo contain a issue (that is really of blur.js) like Edd Turtle mention on his post
Important Note: This technique doesn’t work with local files and has to run through a server, likewise if the background is hosted on the Amazon S3 service you will need to enable cross-domain calls (CORS)..
I suggest you create a directive, restricted to attribute maybe, and have that applying your effect.
Something like this (not tested - and assuming you've included, in this order, jquery, blur.js, then angular;
angular.module('myApp', []).
directive('blurred', function () {
var directive = { restrict: 'A' };
directive.compile = function compile (tElement) {
// taken from blur.js homepage
tElement.blurjs({
source: 'body',
radius: 7,
overlay: 'rgba(255,255,255,0.4)'
});
};
return directive;
});
Then use it:
<p blurred>lorem ipsum</p>
The point with the order I mentioned above, is that if you include jquery before angular, then angular uses it to wrap its dom elements, otherwise it'll use jqlite.
You need to write a angularjs directive for blur.js. Here is an example of how to write a directive for a query plugin:
http://amitgharat.wordpress.com/2013/02/03/an-approach-to-use-jquery-plugins-with-angularjs/
So, I've been talking with co-workers about the "right way" to create an AngularJS controller. I know there are several ways of creating one, but I'm interested in getting my team writing them the same way AND the "right" way. By "right way" I'm talking about easy to read, testable, and performant. I'm sure there are competing theories on the best way to create a controller, but I'm most interested in test-ability at the end of the day since that is what AngularJS is built to do well.
Without further ado, here's the contenders:
Let's assume that our app is declared as so: var app = angular.module('app',[]);
1.
app.controller('myCtrl', function(){
...
});
2.
function myCtrl = {
...
}
app.controller('Ctrl', myCtrl);
3.
(function(app) {
app.controller('myCtrl', function() {
...
}
})(app);
Please let me know if I've missed one.
This does not take into consideration the changes needed for minification so please do not add that to this conversation.
Thanks! (I hope this doesn't start a flame war ><)
My team exclusively uses 1. I've considered 3 as well, and we just have a standing rule (and jshint constraint) about global level code. I would never use 2.
I always do it this way:
angular.module('myModule').controller('MyController', ['$scope', function($scope) {
<stuff>
}]);
Yes, it's a little more verbose, but it creates nothing in global scope, it is very clear what module the controller belongs to, and if I need to separate my controller into another file I just copy and past it without worrying about where 'app' is defined or about whether I missed a '.' in a chained declaration.
And I know I was supposed to ignore it, but of course this version is minification safe.
In general I believe you should find a clear standard and stick to it. That way if something doesn't look "right" you can tell right away.
The Angular team recently posted a best practices guide so that might be a good place to start: http://blog.angularjs.org/2014/02/an-angularjs-style-guide-and-best.html. Also this presentation discusses some best practices on creating controllers: https://docs.google.com/presentation/d/1OgABsN24ZWN6Ugng-O8SjF7t0e3liQ9UN7hKdrCr0K8/present?pli=1&ueb=true&slide=id.p
If you were using number 2 you wouldn't really need app.controller('Ctrl', myCtrl);. You can reference a controller from ng-controller even if it isn't defined with module.controller(...)
You might want to also consider making your controller as much like "classes" as javascript will allow and using the 'controller as' syntax.
var myApp = angular.module("myApp", []);
myApp.MyCtrl = function($log) {
this.$log = $log;
}
myApp.MyCtrl.prototype.sayHello = function() {
this.$log('hello');
}
There are cases where it may be useful to have your controllers globally accessible. Like if you want to create an instance of your controller with $injector.instantiate() you need to have access to its constructor (although you could use the $controller service to accomplish the same goal using a string).
var myCtrl = $injector.instantiate(myApp.MyCtrl); //Works
var myCtrl2 = $injector.instantiate('MyCtrl'); //Doesn't Work
But if you don't have a specific use case for making your controllers global you should probably encapsulate them with module.controller(...);.
This answer also advocates using module.controller() https://stackoverflow.com/a/13363482/373655