Retrieve AngularJS app name - angularjs

How can I retrive the name of the current app in AngularJS?
I mean the ng-app="foo" value.
I have searched through the API documentation, but I could not find any reference to this.
MY SOLUTION
Actually I have found solution like this
angular.element($('[ng-app]')).attr('ng-app');
But I don't really like the idea to search through DOM just to get this information.
Do you know a better solution?

From the $rootElement docs:
The root element of Angular application. This is either
the element where ngApp was declared or the element passed into
angular.bootstrap.
If you inject it you can get the main module name without scanning the DOM:
<html ng-app="myApp">
...
app.controller('MyCtrl',
[
'$scope',
'$rootElement',
function($scope, $rootElement) {
console.log($rootElement.attr('ng-app')); // --> myApp
}
]
);

Related

AngularJS dependency injection - confusing syntax

I have the following code:
<!doctype html>
<html>
<body>
<div ng-controller="MyController">
Hello {{greetMe}}!
</div>
<script src="http://code.angularjs.org/snapshot/angular.js"></script>
<script>
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
angular.element(function() {
angular.bootstrap(document, ['myApp']);
});
</script>
</body>
</html>
from the website: https://docs.angularjs.org/guide/bootstrap
I really can't understand how the syntax is working, particularly,
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
What does the above ugly syntax mean? What is the role of 'MyController'? what does the array parameter mean? what does $scope mean? Who is calling the "function($scope)"?
How does it work?
angular.bootstrap(document, ['myApp']);
When is the parameter above ['myApp'] injected and how?
The website doesn't explain anything regarding the syntax. Just assumed the reader knows all about it.
Please help.
Angular's dependency injection "stringifies" the function and then extracts the parameter names from the string, and uses that to find the dependant service.
However when you minify your code, those parameters because "g", "e", etc. Since Angular now can't know what service you actually wanted, they provide two different methods of explicitly describing your dependencies.
The first is to supply your function/class as the last parameter in an array, with the elements in the array before it being the original names of the parameters.
The alternative is to pass your original function/class, but to assign a "static" $inject property to the function itself. The property is given the value of an array of strings representing your original parameter names.
And, finally, the first parameter supplied to angular.controller/service/factory/etc is the name that you will be applying to the service you are registering. It is that string that other services will use to declare their dependency on your controller/service.
"myApp", in your sample, is a module. Modules aren't injected as dependencies but are instead a way of packaging up a group of services (controllers, directives). You can't inject a service from a different module without first declaring a dependency on that module by adding the name of the module to the array passed as the second parameter to angular.module. angular.bootstrap allows a module (and it's dependants) to work with a dom node.
May be below explanation give you clear understanding
angular.module('myApp', [])
This line creates variable for module (in this case myApp) which we will using in the HTML page to bootstrap the application from the element specified
Either by manul bootstrapping using below line of code
angular.bootstrap(document, ['myApp']);
or by adding to any element where we want to use angular
$scope is the application object and available for both view and controller which contains model data
ng-controller directive will allow to use controller specified (in this case ng-controller ="MyController")
One module can have multiple controllers and each controller will have its own associated $scope object and constructor function model properties and functions are defined inside that associated scope.
Angular Dependency Injection feature will help to consume the components created separately and thereby make those components reusable, maintainable and testable.
Below article on dependency injection will provide more insight
http://anandmanisankar.com/posts/angularjs-dependency-injection-demystified/
Hope this is helpful for you

angular-ui: where is the page $scope inside a <script> element? For a google chart

I'm trying to add a chart to code created by others.
I understand a bit of angular, only...
I'm using angular-ui, so I don't have access to the HEAD tag where the simple Google instructions say to put the SCRIPT tags. I tried putting it later in the html, with other SCRIPT tags, but it kept saying "google" was undefined.
Finally, it seems to work if I put it inside the onload function:
<script src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
drawCharts = function() {
var is = issue;
... create the chart using data inside $scope.issue
}
// google.charts.load( -- DOESN'T WORK HERE, google is undefined
$(window).load(function () {
// finally, in here, 'google' is defined
google.charts.load('current', {'packages': ['corechart', 'bar']});
google.charts.setOnLoadCallback(drawCharts);
}
PROBLEM: drawCharts() needs to access the $scope, but here there's no access to $scope, so my angular data isn't accessible and drawCharts() fails.
So somewhere I need to connect
google.charts.setOnLoadCallback() and $scope
How?
I found one question where the person had a:
$rootScope
.$on('$viewcontentLoaded', function(...)
But he has it in main.js, and I don't have a main.js.
I tried putting it in my controller for the page, but it doesn't define $rootScope. I tried adding $rootScope to the parameters passed to the first line of my controller:
people.controller("voterIssueCtrl", function ($rootScope, $scope, $http, $cookieStore, $window, ClIENT
And that took care of the undefined $rootScope, but the $viewContentLoaded function was never called (it just contained a console.log() message...)
Perhaps my app.js is his main.js.
But it references the controller by name, so it probably loads it, so it probably can't reference something the controller defines.
Help?
===============
I pulled a google chart directive from the web
added the tag in index.html to pull it in
and added the directive to my module definition.
(Of course I forgot the 2nd one and the code didn't complain...)
Nothing. But no complaint that Google wasn't known...
Putting in sample data helps.
In the grand style of js and angular, it doesn't complain if the data isn't exactly in the form it needs...
If only Angular2 + Typescript had been invented sooner...

How to inject HTML using Angular 1.4?

I have a data source that contains an array of raw HTML strings. I must display these in a page to the user.
Being a bit new with Angular, the first thing I tried was this:
<div ng-repeat="html in ctrl.html" ng-bind="html"></div>
This causes Angular to escape my HTML and display it as a string. It isn't what I need, but at least it shows that Angular is, indeed, loading the data.
Doing a Google search, I read about the ng-bind-html-unsafe directive, which I understand is supposed to inject text into an HTML document without escaping or sanitizing it in any way, which is what I want because I must trust our data source.
<div ng-repeat="html in ctrl.html" ng-bind-html-unsafe="html"></div>
This doesn't work, either. It just shows me a blank page. When I open the document inspector, I see that there is a div tag for each entry in the HTML array, but the divs are all blank.
Doing more Google-fu, I found discussions about calling methods on $scope to make Angular play nice with this. They say that ng-bind-html-unsafe is deprecated.
With all the talk about different ways to do what I need with different versions of Angular, how do I do this with today's version: 1.4?
I think you have to "sanitize" your html's..
Example:
angular.module('sanitizeExample', ['ngSanitize'])
.controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
this.html = array with your htmls;
this.sanitizeHtml = function(html) {
return $sce.trustAsHtml(html);
};
}]);
Then
<div ng-repeat="html in ctrl.html" ng-bind-html="ctrl.sanitizeHtml(html)"></div>
I think it will work
use ngSanitize module...
var app = angular.module("myApp", ['ngSanitize']);
see this link. this work perfect
In view
<div ng-repeat="html in ctrl.html" ng-bind-html="ctrl.sanitizeHtml(html)"></div>
In controller
myApp.filter('unsafe', function($sce) { return $sce.trustAsHtml; });
This will work

AngularJS - Directive not recognizing controller

If I have a directive and a controller in the same file:
var app = angular.module('app.navigation', []);
app.controller('NavItemCtrl', [ ....])
app.directive('navItem', [
'ribbon', '$window', function (ribbon, $window) {
return {
require: ['^navigation', '^?navGroup'],
restrict: 'AE',
controller: 'NavItemCtrl',
...
}])
Everything is fine, but if I move the controller code to a different file, because the current file is becoming too clutered, using the same module, and referencing the new controller file in my index page, the directive screams
p0=NavItemCtrl&p1=not aNaNunction got undefined
My index page is like this:
<html>
<body>
....
<script app.js ...>
<script new controller file path .... >
<script original directive file path .... >
....
</body>
</html>
What am I missing here?
[Solution] Delta is right, I figured it out:
For good housing keeping, I think it may be wise to have one JS file, listed as a dependency in the main app.js, that instantiates all the modules you will use, assuming your project is becoming large, and then reuse that instantiate w/o having any dependencies.
As example:
(1) Main App:
angular.module('MainApp', ['ngRoute', 'ngAnimate', 'app.SubApp1', 'app.SubApp2', 'app.SubApp3' ...]
(2) Then as a repository, if you will, create a new js file, say repositoryApp.js, instantiating these sub apps, making sure that this file is referenced before all other files that will use these sub app modules:
angular.module('app.SubApp1', [xxx]);
angular.module('app.SubApp2', [xxx]);
angular.module('app.SubApp3', [xxx]);
(3) Then when creating a series of directives, controllers, or whatever pertaining to a particular sub app, merely reference that sub app in the respective file as:
angular.module('app.SubApp1').controller('foo') .....
angular.module('app.SubApp1').directive('bar') .....
Without the dependency brackets as that is what threw the error for me.
in your directive are you getting you app like this
var app = angular.module('app.navigation');
if you put the brackets after it like your first example you will just be replacing what you have currently instead of getting it.
This get a new module
var app = angular.module('app.navigation', []);
This gets an existing modules.
var app = angular.module('app.navigation');
Notice the exclusion of the brackets in the second example.

re-open and add dependencies to an already bootstrapped application

Is there a way to inject a late dependency to an already bootstrapped angular module? Here's what I mean:
Say that I have a site-wide angular app, defined as:
// in app.js
var App = angular.module("App", []);
And in every page:
<html ng-app="App">
Later on, I'm reopening the app to add logic based on the needs of the current page:
// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
Now, say that one of those on-demand bits of logic also requires their own dependencies (like ngTouch, ngAnimate, ngResource, etc). How can I attach them to the base App? This doesn't seem to work:
// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped
I realize I can do everything in advance, i.e -
// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);
Or define every module on its own and then inject everything into the main app (see here for more):
// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
// ...
}])
// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])
But this will require I initialize the App everytime with the current page's dependencies.
I prefer to include the basic app.js in every page and simply introduce the required extensions to each page (reports.js, home.js, etc), without having to revise the bootstrapping logic everytime I add or remove something.
Is there a way to introduce dependencies when the App is already bootstrapped? What is considered the idiomatic way (or ways) to do this? I'm leaning towards the latter solution, but wanted to see if the way I described could also be done. thanks.
I solved it like this:
reference the app again:
var app = angular.module('app');
then push your new requirements to the requirements array:
app.requires.push('newDependency');
Simple...
Get an instance of the module using the getter like this:
var app = angular.module("App");
Then add to the "requires" collection like this:
app.requires[app.requires.length] = "ngResource";
Anyway, this worked for me. GOOD LUCK!
According to this proposal on the Angular JS google group this functionality does not exist as of this moment. Hopefully the core team decides to add this functionality, could use it myself.
If you wish to add multiple dependencies at once, you can pass them in push as follows:
<script>
var app = angular.module('appName');
app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>
I realize that this is an old question, however, no working answer has yet been provided, so I decided to share how I solved it.
The solution requires forking Angular, so you can't use CDN anymore. However the modification is very small, so I am surprised why this feature doesn't exist in Angular.
I followed the link to google groups that was provided in one of the other answers to this question. There I found the following code, which solved the issue:
instanceInjector.loadNewModules = function (mods) {
forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};
When I added this code to line 4414 in the angular 1.5.0 source code (inside the createInjector function, before the return instanceInjector; statement), it enabled me to add dependencies after bootstrapping like this $injector.loadNewModules(['ngCookies']);.
Since version 1.6.7 it is now possible to lazy load modules after the app has been bootstrapped using $injector.loadNewModules([modules]). Below is an example taken from AngularJS documentation:
app.factory('loadModule', function($injector) {
return function loadModule(moduleName, bundleUrl) {
return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
};
})
Please read full documentation about loadNewModules as there are some gotchas around it.
There's also a very good sample app by omkadiri using it with ui-router.

Resources