I am learning Angular and adding a controller to my module only works when all the code is inline on the page. If I replace it with <script src="myModuleFile.js"></script> it fails with
"Error: [$injector:unpr]
http://errors.angularjs.org/1.3.11/$injector/unpr?p0=aProvider%20%3C-%20a%20%3C-%20personController
var app = angular.module('app', [])
.config([function(injectables){
console.log('configuring app');
}]).run([function(injectables){
console.log('running app');
}]).controller("personController", function($scope){
$scope.firstName = "John";
$scope.lastName = "Doe";
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="web/stylesheets/app.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<!-- wont work if I include it this way -->
<script src="web/js/app.min.js"></script>
<!-- but works if I put it in here -->
<script></script>
</head>
<body>
<label>Name:</label>
<input type="text" ng-model="yourName" placeholder="Enter a name here"><hr />
<h1>Hello {{ yourName }}!</h1>
<div ng-init="firstName='John'">
<p>The name is <span ng-bind="firstName"></span></p>
</div>
<p>My first expression: {{ 5 + 5 }}</p>
<div ng-controller="personController">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<div ng-init="names=[
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}]">
<ul>
<li ng-repeat="x in names">
{{ x.name + ', ' + x.country }}
</li>
</ul>
</div>
<button ng-click="count = count + 1">Click me!</button>
<p>{{ count }}</p>
</body>
</html>
As Claies mentioned in the comments, the error message looks like it is trying to find a provider for a dependency "a", which is probably a result of minification.
If you do like:
angular.module(..).controller("SomeCtrl", function($scope){});
It might minify $scope to just a. So instead you should use:
angular.module(..).controller("SomeCtrl", ["$scope", function($scope){}]);
Because the string will not be minified, Angular will know which dependency is which. Another way would be to use $injector of course, as Claies also mentioned.
Related
I have the following array of objects, which is a server response. I am trying to use ng-repeat to iterate over this array and read each value.
While trying to use in html, array[0].value is working while using ng-repeat, nothing is working.
After a lot of debugging, I am unable to understand how ng-repeat is working for arrays.
Here is my example:
messages array:
[
{"Id":14,"Text":"hii hello","count":750},
{"Id":10009,"Text":"test message","count":6}
]
The following is used in html:
<div class="my-message" layout="row" layout-align="center center">
{{messages}} <!-- printing the above array -->
<div ng-repat="message in messages">
{{ message.Id}}<!-- printing nothing -->
</div>
{{ messages[0].Id }} <!-- printing 14 !-->
</div>
The array is in scope and it is also seen in this html as the {{ message }} array is printing properly.
Can someone help me understand the working of ng-repeat and where am I missing
In your controller you must have :
$scope.messages = [{"Id":1,...},...]
There is a typo in your view code (ng-repat -> ng-repeat):
<div ng-repat="message in messages">
{{ message.Id}}
</div>
must be :
<div ng-repeat="message in messages">
{{ message.Id}}
</div>
It should be fine like this.
Have fun
hope this will clears you
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<div class="my-message" layout="row" layout-align="center center">
{{messages}} <!-- printing the above array -->
<div ng-repeat="message in messages">
{{ message.Id}}
{{ message.Text }}
{{ message.count }}
</div>
</div>
</body>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.messages =[
{"Id":14,"Text":"hii hello","count":750},
{"Id":10009,"Text":"test message","count":6}
];
});
</script>
</html>
The issue is with typo in using "ng-repeat", after correcting it my code worked normally as expected.
Why the output for second div tag is displaying normal? Why there is no binding of angular js with it?
Could you please explain me?
<!DOCTYPE html>
<html>
<head>
<title>Angular JS Demo</title>
<script src="scripts/angular.min.js"></script>
<script src="scripts/Script.js"></script>
<meta charset="utf-8" />
</head>
<body>
<div ng-app="myApp1" ng-controller="myCtrl">
{{ first_name +" "+ last_name }}
</div>
<div ng-app>
10 +20 = {{ 10 + 20 }}
{{ 1 == 2 }}
{{ ['ajay','kumar','hari','bag'][0] }}
</div>
<script>
var my_module = angular.module("myApp1", []);
var my_Controller = function ($scope) {
$scope.first_name = "vijay";
$scope.last_name = "kumar";
}
my_module.controller("myCtrl", my_Controller);
</script>
</body>
</html>
-----------output------
vijay kumar
10 +20 = {{ 10 + 20 }} {{ 1 == 2 }} {{ ['ajay','kumar','hari','bag'][0] }}
Try like this.
var app = angular.module('myApp1', []);
app.controller('myCtrl', function($scope) {
$scope.first_name = "vijay";
$scope.last_name = "kumar";
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body >
<div ng-app="myApp1" ng-controller="myCtrl">
{{ first_name +" "+ last_name }}
<div>
10 +20 = {{ 10 + 20 }}
{{ 1 == 2 }}
{{ ['ajay','kumar','hari','bag'][0] }}
</div>
</div>
</body>
As specified in the AngularJS docs only one AngularJS application can be auto-bootstrapped per HTML document. The first ng-app found in the document will be used to define the root element to auto-bootstrap as an application. If you want to use another ng-app you should manually bootstap the app.
See the angularJS docs section for the detailed explanation.
https://docs.angularjs.org/api/ng/directive/ngApp
From AngularJS documentation -
only one AngularJS application can be auto-bootstrapped per HTML
document.
In other words, ng-app directive can be used only once in your entire application. S
In your case, ng-app is limited to just one div tag. Outside this div tag, angularjs' features won't be accessible. you can have a parent div with the ng-app directive, followed by the current divs. Or simply but the directive in your body tag.
<!DOCTYPE html>
<html>
<head>
<title>Angular JS Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="scripts/Script.js"></script>
<meta charset="utf-8" />
</head>
<body>
<div ng-app="myApp1"> <!-- parent div -->
<div ng-controller="myCtrl">
{{ first_name +" "+ last_name }}
</div>
<div ng-app>
10 +20 = {{ 10 + 20 }}
{{ 1 == 2 }}
{{ ['ajay','kumar','hari','bag'][0] }}
</div>
</div>
<script>
var my_module = angular.module("myApp1", []);
var my_Controller = function ($scope) {
$scope.first_name = "vijay";
$scope.last_name = "kumar";
}
my_module.controller("myCtrl", my_Controller);
</script>
</body>
</html>
This question already has answers here:
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
(3 answers)
Closed 7 years ago.
I have a problem when i try to fragment my html with ng-include:
This is what my index.html page looks like when it works (prix=price, TVA=tax):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="style.css" />
<title> TVA </title>
</head>
<body>
<div>
<div ng-app="app" ng-controller="appCtrl">
<input ng-model="tva" placeholder="TVA" /><br />
<input ng-model="prix" placeholder="Prix" />
<select ng-model="taxe">
<option>HT</option>
<option>TTC</option>
</select>
<button id="btn" ng-click="calcul()">Calculer</button>
<p>{{ total }}</p>
</div>
</div>
<script src="angular.min.js"></script>
<script src="script.js"></script>
</body>
</html>
The script.js :
app = angular.module('app', []);
app.controller('appCtrl', ['$scope', function ($scope) {
$scope.calcul = function() {
if ($scope.taxe == "TTC") {
$scope.total = parseInt($scope.prix) + $scope.prix * $scope.tva /100;
} else if($scope.taxe == "HT") {
$scope.total = 1/(1+$scope.tva/100)*$scope.prix;
}
};
}]);
So this works, the result is an number (the price with or without tax).
When I use the ng-include like this:
<div>
<div ng-app="app" ng-controller="appCtrl">
<div ng-include="'tva.html'"></div>
<input ng-model="prix" placeholder="Prix" />
<select ng-model="taxe">
<option>HT</option>
<option>TTC</option>
</select>
<button id="btn" ng-click="calcul()">Calculer</button>
<p>{{ total }}</p>
</div>
</div>
I only tried to replace the first input with a new HTML page.
The tva.html :
<input ng-model="tva" placeholder="TVA" /><br />
Now the results show "NaN" (I put those codes on a server so that I can check online). Why is this?
#Josh Beam Answered & explained ng-include creates a child scope on creating the DOM. I'd suggest you to use dot rule in angular that will follow prototypal inheritance on that object and you object value will access in child scope.
Now your object structure will changed to $scope.model={}; and this model will have all the input values. like all will become like model.prix, model.taxe & model.tva so that the prototypal inheritance will follow.
Markup
<div ng-app="app" ng-controller="appCtrl">
<div ng-include="'tva.html'"></div>
<br />
<input ng-model="model.prix" placeholder="Prix" />
<select ng-model="model.taxe">
<option>HT</option>
<option>TTC</option>
</select>
<button id="btn" ng-click="calcul()">Calculer</button>
<p>{{ total }}</p>
</div>
Code
app.controller('appCtrl', ['$scope', function ($scope) {
$scope.model = {};
$scope.calcul = function() {
if ($scope.model.taxe == "TTC") {
$scope.total = parseInt($scope.model.prix) + $scope.model.prix * $scope.model.tva /100;
} else if($scope.model.taxe == "HT") {
$scope.total = 1/(1+$scope.model.tva/100)*$scope.model.prix;
}
};
}]);
tva.html
<input ng-model="model.tva" placeholder="TVA" /><br />
Demo Plunkr
Short answer: don't use ng-include in this instance.
Long answer: ng-include creates a new child scope, so ng-model inside the ng-include isn't appCtrl's TVA. I don't see a reason here to use ng-include anyway, your code is fine without it.
So basically you're getting NaN (not a number) because $scope.TVA is never set when using the ng-include... you're attempting to multiply an undefined variable by another number, which returns NaN:
The reason for that is the ng-include creates a new scope under the scope when the HTML was included, but you can access to the parent scope by specifying $parent
<input ng-model="$parent.tva" placeholder="TVA" /><br />
A better approach is give an alias to your controller, so it will be clear semantically to children controllers accessing to a specific parent.
<div ng-app="app" ng-controller="appCtrl as vmMain">
<div ng-include="'tva.html'"></div>
... and in the other file:
<input ng-model="vmMain.tva" placeholder="TVA" /><br />
Here is my code :
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<script type="text/javascript" src="./angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
var app1 = angular.module('myApp1', []);
app.controller('myCtrl', function($scope) {
$scope.firstName = "sparsh";
$scope.lastName = "khandelwal";
});
</script>
<title>Home Page</title>
</head>
<body>
<div ng-app="myApp" ng-init="name='Sparsh'">
<div ng-controller="myCtrl">{{firstName}}</div>
<p>
Name : <input type="text" ng-model="name">
</p>
<h1>Hello {{name}}</h1>
</div>
<div ng-app="myApp1" ng-init="names=['Jani','Hege','Kai']">
<ul>
<li ng-repeat="x in names">{{x}}</li>
</ul>
</div>
<script type="text/javascript">
angular.bootstrap(document, ['myApp1','myApp']);
</script>
</body>
</html>
Although i can see the expected output, but at the same time facing console error.
here is the description of error
(while i click on the url)
it says it already bootstrapped so i remove the 'myApp' from .bootstrap function, but that didnt work.
Please help.
You are doing both ng-app declarations and angular.bootstrap(document, ['myApp1','myApp']);.
You need to choose only one method, otherwise you get the well descripted error of multiple bootstrapped applications.
The problem is as explained in the previous comments, the automatic and manual initialization of modules.
Since you want to initialize them separately for each elements then try an approach like
<div data-app="myApp" ng-init="name='Sparsh'">
<div ng-controller="myCtrl">{{firstName}}</div>
<p>
Name : <input type="text" ng-model="name"/>
</p>
<h1>Hello {{name}}</h1>
</div>
<div data-app="myApp1" ng-init="names=['Jani','Hege','Kai']">
<ul>
<li ng-repeat="x in names">{{x}}</li>
</ul>
</div>
then
var app = angular.module('myApp', []);
var app1 = angular.module('myApp1', []);
app.controller('myCtrl', function ($scope) {
$scope.firstName = "sparsh";
$scope.lastName = "khandelwal";
});
var els = document.querySelectorAll('[data-app]');
for (var i = 0; i < els.length; i++) {
angular.bootstrap(els[i], [els[i].dataset.app]);
}
Demo: Fiddle
My module isn't loading, and I can't figure out why. Could someone help me to find out what I am doing wrong?
The following is my HTML in a file named index.html:
<html ng-app="demoApp">
<head>
<title>Using AngularJS Directives and Data Binding</title>
<script type="text/javascript" src="_Script.js"></script>
<script src="angular.min.js"></script>
</head>
<body>
<!-- Get name out of array with controller using a module-->
<h3>Get names out of an array with controller using a module:</h3>
<div class ="container" ng-controller="SimpleController">
<input type="text" ng-model="search" /> {{ search }}
<ul>
<li ng-repeat="naam in namen | filter:search" >{{ naam }}</li>
</ul>
</div>
</body>
</html>
And this is the Javascript in a file named _Script.js:
var demoApp = angular.module('demoApp', []);
function SimpleController($scope) {
$scope.namen = [
'John',
'Will',
'Alex'
];
}
demoApp.controller('SimpleController', SimpleController);
I've looked for everything, so maybe it is simple. But I can't find it and got stuck with it.
Regards,
You're currently loading your _script.js first, and angular JS second. If you reorder them your script should work: