Want to use multiple ng-app within one application - angularjs

I am working on an application, Where multiple ng-app are defined and used. Initially ng-app on different pages were not conflicting as all the pages were independent but now I have to include a header and header has its own ng-app defined.
I am using two different methods to avoid conflict of header app with other pages app.
First method:
Bootstrapping an app manually on each page:
angular.bootstrap($('#mycontact_container'),['contactsApp']);
OR
angular.element(document).ready(function() {
angular.bootstrap($('#topNavigation'),['headerApp']);
});
Second method:
angular.module("rootApp", ["headerApp", "contactsApp"]);
Where rootApp is an App defined in body tag that will include entire application within it. headerApp is an app defined on header of each page and contactsApp is app of one custom html page.
First method error:
Error: [$injector:modulerr]
http://errors.angularjs.org/1.4.8/$injector/modulerr?p0=headerApp&p1=%5B%24injector%3Amodulerr%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.4.8%2F%24injector%2Fmodulerr%3Fp0
Error on OR part of First method:
Error: [ng:btstrpd]
http://errors.angularjs.org/1.4.8/ng/btstrpd?p0=%26lt%3Bsection%20id%3D%22topNavigation%22%20class%3D%22top-navigation%20ng-scope%22%20ng-app%3D%22headerApp%22%26gt%3B
...f e?JSON.stringify(e):e;d+=c(e)}return Error(d)}}function
za(a){if(null==a||Xa(a...
i.e app is already bootstrapped.
Second Method issue:
No errors but when I try to use interpolate provide in one of my app which is included in header i.e it will be included throughout application using below code:
headerApp.config(['$interpolateProvider',
function($interpolateProvider) {
$interpolateProvider.startSymbol('{$');
$interpolateProvider.endSymbol('$}');
}
]);
app.controller('MainController', ['$scope', '$http',function MainController($scope, $http) {
$scope.first_name = "abc";
});
I get nothing printed using {$ first_name $} in my view. Ultimately my app is misbehaving. I have posted this issue in different post SO question
Can Anyone guide me what exactly I need to follow to correct the behaviour of my application with existing architecture.
I guess only angular experts can guide me well here.
Please let me know if more detailing is required.
Update
I was facing following error when I was manually bootstrapping app:
Error: [ng:btstrpd]
because I was using ng-app within html. When manually bootstrapping app then ng-app is not required.

Related

Why angular.bootstrap() to document throws error

I have my test example in this plunkr link
My question is NOT DUPLICATE of this one
Also the Google Result and Github Bug was about the bug reporter not defining the module which he was trying to bootstrap in the first place
I have 3 modules grandParentModule, parentModule and nestedModule.
I have bootstrapped parentModule and nestedModule to 2 nested div elements and they are working fine.
But as soon as I try to bootstrap grandParentModule to document, it is throwing a console error.
This is my HTML
<div id="parent" ng-app="parentModule">
<div id="nested">
</div>
</div>
And this is my SCRIPT
angular.module('grandParentModule', []);
angular.module('parentModule', []);
angular.module('nestedModule', []);
var nestedElem = document.getElementById("nested");
angular.bootstrap(angular.element(nestedElem), ['nestedModule']);
//comment / uncomment this line to toggle the error at console
angular.bootstrap(document, ['grandParentModule']);
Only this line angular.bootstrap(document, ['grandParentModule']); is causing the error
Uncaught Error: [ng:btstrpd] http://errors.angularjs.org/1.5.5/ng/btstrpd?p0=%26lt%3Bdiv%20id%3D%22parent%22%20ng-app%3D%22parentModule%22%26gt%3B
Can anyone explain to me why is it happening?
This isn't how works angular bootstrapping.
You're supposed,to bootstrap only one module.
If you use multiple independant module, the DOM element where you bootstrap them must not be nested.
Furthermore what are those module supposed to be ?
If they're linked then they must have dependencies between them ie :
angular.module('parentModule', ['grandParentModule']);
If you want to have some nested views with their own controller use either multiple ng-controller or check ui-router on the net.

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...

AngularJS module inside "root module"

Is there a way to define an angular module inside another module ? I have a template in my web application which is called for almost every page of the application. In the template definition I set the ng-app. So for this ng-app I can declare the modules I need in all pages of the application (or almost every page). Now there are some modules I want to add only on specific pages. The problem is that in those pages I already have the ng-app of the template.
So is there a way to keep the ng-app as some kind of root ng-app which declared the modules I need everywhere and then add specific modules inside specific pages too ?
That means is it possible to do something like this:
<div ng-app="rootApp">
<div ng-app="specificApp">
...
</div>
</div>
The rootApp contains the module that are declared in my template, that are use in all the pages, and the specifiApp contains the modules I need only in one specific page.
Thanks !
[EDIT] Bootstrap attempt:
var reportHolidaysByEmployeeApp = angular.module('reportHolidaysByEmployeeApp', ['fitnetApp', 'ui.bootstrap']);
angular.bootstrap(document.getElementById("reportHolidaysByEmployeeApp"), ['reportHolidaysByEmployeeApp']);
reportHolidaysByEmployeeApp.controller('ReportHolidaysByEmployeeCtrl', function($scope, $filter, $timeout) {
fitnetApp is the global Module I load on the html tag in every page
Only one AngularJS application can be auto-bootstrapped per HTML
document. The first ngApp found in the document will be used to define
the root element to auto-bootstrap as an application. To run multiple
applications in an HTML document you must manually bootstrap them
using angular.bootstrap instead. AngularJS applications cannot be
nested within each other. --
http://docs.angularjs.org/api/ng.directive:ngApp
See also
https://groups.google.com/d/msg/angular/lhbrIG5aBX4/4hYnzq2eGZwJ
http://docs.angularjs.org/api/angular.bootstrap
If you are having separate controllers for your pages[views] , add dependency in your controller module to [rootApp] or [spcificApp] as your page needs.
$routeProvider.when('/view1',{
template:
controller:view1controller
})
if u need rootApp as dependency in view1 page
in your controller module
angular.module('GlobalCtrl',['rootApp'])
.controller('view1controller')
'
You cannot have two ng-app in a single web page.
If you need to add dependency module on specific page use
angular.module('reportHolidaysByEmployeeApp').requires.push('thirdpartymodule');
This will dynamically inject dependency in your already running angular application.

Showing and hiding header nav in Mean.js app

I am building a blog with the Yeoman Mean.js generator. So far I am really enjoying working with Mean.js, however I am relatively new to Angular development, so some things just don't click for me yet.
I would like to hide the header on all pages of my app, and only show it if I am logged in. I'll be pulling signup out of the header, and logging in from a single location to manage my blog.
I tried using ng-show="topbarActive" on the <header> element present in the /app/views/layout.server.view.html:
<header ng-show="topbarActive" data-ng-include="'/modules/core/views/header.client.view.html'" class="navbar navbar-fixed-top navbar-default"></header>
I then tried explicitly setting this variable to false in /public/modules/core/controllers/home.client.controller.js:
$scope.topbarActive = false;
I set this value to true in /public/modules/users/controllers/authentication.client.controller.js, in the hopes that I could manually ping http://localhost:3000/#!/signup and see my header bar.
After this set up I do not see the header anywhere. Seeing as how I am new to 'The Angular Way', what steps am I missing in order to achieve the behavior I am looking for. Am I confused in how Mean.js builds it's dependencies?
One of the key concepts in AngularJS is scoping. In this particular case your controller HomeController is assigned to the first div under the header. That makes HomeController scope unavailable to it's parent (header) which actually doesn't have any controller at all.
To make your configuration work, please add a new controller, for example:
/* /public/modules/core/controllers/body.client.controller.js */
'use strict';
angular.module('core').controller('BodyController', ['$scope', 'Authentication', 'Menus',
function($scope, Authentication, Menus) {
$scope.topbarActive = true;
}]);
And then add this controller to the body in layout.server.view.html:
<body ng-cloak ng-controller="BodyController">
Alternatively you can create a controller for your tag only, depends on where you're going from here.

angularjs controller executes twice

A similar question was asked here but it did not help me.
I am learning angularjs and I noticed the controller is executed twice.
I have a very simple fiddle example that shows the behavior here
I built the example as I was learning about services and at first I thought it was the injecting of the services into the controller but I commented all the code related to the services and still the controller is executed twice.
My example works but I am afraid I am doing something wrong.
<div ng-app="MyApp">
<div ng-controller="MyCtrl">
{{data1}}
</div>
</div>
var app = angular.module('MyApp', [])
app.service('Service1', function(){
return {
ajxResponse1: 'dataFromService1'
};
});
function MyCtrl($scope, Service1){
alert('Entering MyCtrl');
$scope.data1 = Service1.ajxResponse1;
alert('Exiting MyCtrl');
}
One possible source is this: if you are using Routing and specify the controller in routes - you must not specify it in template that the route uses. We had that problem when this was overlooked.
Your controller was running twice in the fiddle because angular is referenced twice (once via the Frameworks & Extensions drop down and another as an External Resource).
See this updated fiddle where I removed the External Resource and the alerts only show up once.
The code remains unchanged:
function MyCtrl($scope, Service1, Service2, Service3){
alert('Entering MyCtrl');
$scope.data1 = Service1.ajxResponse1;
$scope.data2 = Service2.ajxResponse2;
$scope.data3 = Service3.ajxResponse3;
alert('Exiting MyCtrl');
}
I had a similar problem and it was due to slashes in my routing.
I had something like /post{slug:[a-z0-9-]*/} for my route and when visiting the page at domain.com/post it would redirect to the version with a slash on the end.
Took me ages to work it out!
Edit:
Actually, just took a more detailed look at your code and noticed there is no routing in there, so this is probably not the cause in your case.
Might be useful for people like me who were looking for a different solution though.
For all the people using rails and angularjs:
The rails framework that maps URLS to views and loads them clashes with the angularjs $route even when you have a single-view application.
To prevent the double-loading of your controller:
go to application.js and remove "//= require turbolinks
You're welcome.

Resources