I'm trying to add two angular apps / modules to one page.
In the fiddles below you can see that always only the first module, referenced in the html code, will work correctly, whereas the second is not recognized by angular.
In this fiddle we can only execute the doSearch2 method, whereas in this fiddle only the doSearch method works correctly.
I'm looking for the way how to correctly place two angular modules into one 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
I created an alternative directive that doesn't have ngApp's limitations. It's called ngModule. This is what you code would look like when you use it:
<!DOCTYPE html>
<html>
<head>
<script src="angular.js"></script>
<script src="angular.ng-modules.js"></script>
<script>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
</script>
</head>
<body>
<div ng-modules="MyModuleA, MyModuleB">
<h1>Module A, B</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
</body>
</html>
You can get the source code at:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/
It's essentially the same code used internally by AngularJS without the limitations.
Why do you want to use multiple [ng-app] ? Since Angular is resumed by using modules, you can use an app that use multiple dependencies.
Javascript:
// setter syntax -> initializing other module for demonstration
angular.module('otherModule', []);
angular.module('app', ['otherModule'])
.controller('AppController', function () {
// ...do something
});
// getter syntax
angular.module('otherModule')
.controller('OtherController', function () {
// ...do something
});
HTML:
<div ng-app="app">
<div ng-controller="AppController">...</div>
<div ng-controller="OtherController">...</div>
</div>
EDIT
Keep in mind that if you want to use controller inside controller you have to use the controllerAs syntax, like so:
<div ng-app="app">
<div ng-controller="AppController as app">
<div ng-controller="OtherController as other">...</div>
</div>
</div>
You can bootstrap multiple angular applications, but:
1) You need to manually bootstrap them
2) You should not use "document" as the root, but the node where the angular interface is contained to:
var todoRootNode = jQuery('[ng-controller=TodoController]');
angular.bootstrap(todoRootNode, ['TodoApp']);
This would be safe.
Manual bootstrapping both the modules will work. Look at this
<!-- IN HTML -->
<div id="dvFirst">
<div ng-controller="FirstController">
<p>1: {{ desc }}</p>
</div>
</div>
<div id="dvSecond">
<div ng-controller="SecondController ">
<p>2: {{ desc }}</p>
</div>
</div>
// IN SCRIPT
var dvFirst = document.getElementById('dvFirst');
var dvSecond = document.getElementById('dvSecond');
angular.element(document).ready(function() {
angular.bootstrap(dvFirst, ['firstApp']);
angular.bootstrap(dvSecond, ['secondApp']);
});
Here is the link to the Plunker
http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview
NOTE: In html, there is no ng-app. id has been used instead.
I made a POC for an Angular application using multiple modules and router-outlets to nest sub apps in a single page app.
You can get the source code at: https://github.com/AhmedBahet/ng-sub-apps
Hope this will help
Related
I am developing in angular js. Previously, i use ng-include with url. But how could i point the url to templatecache?
<ng-include
src="string"
[onload="string"]
[autoscroll="string"]>
...
</ng-include>
Template cache uses a key for identifying the cached elements, so you can use the key for that.
$templateCache.put('MY KEY', 'Cached content');
And in the html:
<ng-include src="'MY KEY'"></ng-include>
See it on AngularJS docs for $templateCache.
There are two ways:
In markup:
Specify your template as a script tag:
<script type="text/ng-template" id="templateId.html">
<p>This is the content of the template</p>
</script>
(this should be a descendant of your ng-app, in other words it should be specified somewhere inside the ng-app markup)
This will automatically cache the template.
In code:
var myApp = angular.module('myApp', []);
myApp.run(function($templateCache) {
$templateCache.put('templateId.html', 'This is the content of the template');
});
In both the cases, you can get the cached template like this:
<div ng-include=" 'templateId.html' "></div>
or
$templateCache.get('templateId.html')
I'm trying to add two angular apps / modules to one page.
In the fiddles below you can see that always only the first module, referenced in the html code, will work correctly, whereas the second is not recognized by angular.
In this fiddle we can only execute the doSearch2 method, whereas in this fiddle only the doSearch method works correctly.
I'm looking for the way how to correctly place two angular modules into one 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
I created an alternative directive that doesn't have ngApp's limitations. It's called ngModule. This is what you code would look like when you use it:
<!DOCTYPE html>
<html>
<head>
<script src="angular.js"></script>
<script src="angular.ng-modules.js"></script>
<script>
var moduleA = angular.module("MyModuleA", []);
moduleA.controller("MyControllerA", function($scope) {
$scope.name = "Bob A";
});
var moduleB = angular.module("MyModuleB", []);
moduleB.controller("MyControllerB", function($scope) {
$scope.name = "Steve B";
});
</script>
</head>
<body>
<div ng-modules="MyModuleA, MyModuleB">
<h1>Module A, B</h1>
<div ng-controller="MyControllerA">
{{name}}
</div>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
<div ng-module="MyModuleB">
<h1>Just Module B</h1>
<div ng-controller="MyControllerB">
{{name}}
</div>
</div>
</body>
</html>
You can get the source code at:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/
It's essentially the same code used internally by AngularJS without the limitations.
Why do you want to use multiple [ng-app] ? Since Angular is resumed by using modules, you can use an app that use multiple dependencies.
Javascript:
// setter syntax -> initializing other module for demonstration
angular.module('otherModule', []);
angular.module('app', ['otherModule'])
.controller('AppController', function () {
// ...do something
});
// getter syntax
angular.module('otherModule')
.controller('OtherController', function () {
// ...do something
});
HTML:
<div ng-app="app">
<div ng-controller="AppController">...</div>
<div ng-controller="OtherController">...</div>
</div>
EDIT
Keep in mind that if you want to use controller inside controller you have to use the controllerAs syntax, like so:
<div ng-app="app">
<div ng-controller="AppController as app">
<div ng-controller="OtherController as other">...</div>
</div>
</div>
You can bootstrap multiple angular applications, but:
1) You need to manually bootstrap them
2) You should not use "document" as the root, but the node where the angular interface is contained to:
var todoRootNode = jQuery('[ng-controller=TodoController]');
angular.bootstrap(todoRootNode, ['TodoApp']);
This would be safe.
Manual bootstrapping both the modules will work. Look at this
<!-- IN HTML -->
<div id="dvFirst">
<div ng-controller="FirstController">
<p>1: {{ desc }}</p>
</div>
</div>
<div id="dvSecond">
<div ng-controller="SecondController ">
<p>2: {{ desc }}</p>
</div>
</div>
// IN SCRIPT
var dvFirst = document.getElementById('dvFirst');
var dvSecond = document.getElementById('dvSecond');
angular.element(document).ready(function() {
angular.bootstrap(dvFirst, ['firstApp']);
angular.bootstrap(dvSecond, ['secondApp']);
});
Here is the link to the Plunker
http://plnkr.co/edit/1SdZ4QpPfuHtdBjTKJIu?p=preview
NOTE: In html, there is no ng-app. id has been used instead.
I made a POC for an Angular application using multiple modules and router-outlets to nest sub apps in a single page app.
You can get the source code at: https://github.com/AhmedBahet/ng-sub-apps
Hope this will help
I'm dealing with a content management system that needs to "inject" a reusable component into a page.
I want to inject the following component (html and javascript).
<script type="text/javascript">
if(typeof angular == 'undefined') {
document.write(unescape("%3Cscript type='text/javascript' src='/resources/scripts/lib/angular.min.js'%3E%3C/script%3E"));
document.write(unescape("%3Cscript type='text/javascript' src='/resources/scripts/pricing/app.js'%3E%3C/script%3E")); }
}
</script>
<div ng-app="pricing" ng-controller="PriceController as pc" ng-init="pc.getPrices('myprod', 'PER')">
Some text {{ pc.prices.msg["startdat tarief"] | jsDate }} .
More text {{ pc.prices.msg["einddat product"] | jsDate }}.
</div>
The component must be able to be injected multiple times on the page.
The problem is that the controller works fine, but only for the first injection.
This probably has something to do with that I am using the same app multiple times.
I am fairly new to angular.
How can I inject the same component multiple times?
Note that I am not able to init the app on a higher level. Because this would require the content manager to edit all pages, we juist want to inject a HTML component with javascript (i.e. the code snippet).
If you are able to add a unique ID to the module div you can manually bootstrap your angular app as follows:
function bootstrapAngular(id) {
angular.bootstrap(document.getElementById('module-' + id), ['app']);
}
angular.module('app', []).controller('sample', function ($scope) {
$scope.foo = 'bar';
});
bootstrapAngular(1);
bootstrapAngular(2);
bootstrapAngular(3);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div id="module-1">
<div ng-controller="sample">
{{ foo }}
</div>
</div>
<div id="module-2">
<div ng-controller="sample">
{{ foo }}
</div>
</div>
<div id="module-3">
<div ng-controller="sample">
{{ foo }}
</div>
</div>
You cannot have multiple ng-App directives on a single page. From the Angular.js documentation:
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.
If placing ng-App higher in the tree isn't an option, you will have to re-write the components so that each component gets a unique angular.module() and when the component is injected, it will need to fire angular.bootstrap().
I'm new to angular, I've tried some testing pattern and it's ok with the $scope variable but I can't make it work for a simple controller nesting. (and avoid using the $scope variable, instead I want to use "this")
Here is my sample HTML and javascript :
<!doctype html>
<html ng-app="appTest">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
</head>
<body>
<div ng-controller="FirstController as first">
<div>
First is {{first.text}}
</div>
<div ng-controller="SecondController as second">
Second is {{second.text}}
</div>
</div>
<script>
var app = angular.module("appTest",[]);
function printFirst() {
this.text = "first"
}
function printSecond() {
this.text = "second";
}
app.controller("FirstController",[printFirst]);
app.controller("SecondController",[printSecond]);
</script>
</body>
</html>
In the output html the angular variables inside curly brackets are not replaced and I don't know what's going on. I've tried to install Angular Batarang for debugging but the scope console is empty.
Obviously it's a silly mistake but I don't see where I'm wrong
Ok, the answer has nothing to do with my code, I was just using a too old version of Angularjs (1.0.8).
I moved to the last version 1.3.4 and it works fine.
Access the variable using $scope.text please instead of this.text.
How do I make a jsfiddle out of the following code:
<html>
<head>
</head>
<body>
<div ng-app ng-controller="MainCtrl">
<ul>
<li ng-repeat="num in nums">
{{num}}
</li>
</ul>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.js"></script>
<script type="text/javascript" charset="utf-8">
function MainCtrl($scope) {
$scope.nums = ["1","2"];
}
</script>
</body>
</html>
My non working attempt: http://jsfiddle.net/zhon/3DHjg/ shows nothing and has errors.
You need to set some things up in jsFiddle for this to work.
First, on the left panel, under "Frameworks & Extensions", select "No wrap - in <body>".
Now, under "Fiddle Options", change "Body tag" to <body ng-app='myApp'>
In the JS panel, initiate your module:
var app = angular.module('myApp', []);
Check it out: http://jsfiddle.net/VSph2/1/
#pkozlowski.opensource has a nice blog post about how to use jsFiddle to write AngularJS sample programs.
You've defined your controller in a function scope that is not accessible to angular (angular is not yet loaded). In other words you are trying to call angular library's functions and helpers like below example before getting angular library loaded.
function onload(){
function MainCtrl(){}
}
To resolve this, switch your angular load type to be No wrap - in <body> like shown in screenshot.
here is a working example in jsfiddle
Click JAVASCRIPT button, choose angular version and place where u want include loaded script:
Then click HTML button and add ng-app in body tag. Its all:)
I am writing my answer for those who land on this page , I was used to use ng-module directive but in jsfiddle after half an hour I realized that ng-module is not allowed and you see no error , and when changed that ng-module to ng-app fiddle worked very well .I just wanted to share this .And no wrap (body) is required too.
<div ng-app="appX" ng-controller="appCtrl">
<p>{{greeting}}
</p>
</div>
var app=angular.module("appX",[]);
console.log(app);
app.controller("appCtrl",function($scope){
$scope.greeting="Hello World";
});
https://jsfiddle.net/cloudnine/trgrjwf1/7/
Since Angular 1.4.8 has been chosen by JSFiddle as the top option for Angular V1 in its JAVASCRIPT setting panel, more restriction applies: both ng-app and ng-controller should be declared in HTML to make it work.
Sample HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<input type="text" ng-model="sample" placeholder="type something here...">
<span>{{sample}}</span>
</div>
Sample JS:
angular.module('myApp', [])
.controller('myCtrl', function($scope) {});
https://jsfiddle.net/y170uj84/
Also tested with the latest Angular 1.6.4, by setting as External Resource.
For little experiments in angular 5, you can use https://stackblitz.com/.
This site is used in angular documentation to run live demo. For example, https://stackblitz.com/angular/eybymjopmav