This is a nooob question - as in I started learning Angular today. I was following the tutorial at Angular JS in 30 mins
The idea is to setup basic databinding in Angular. The code displays an input box, and shows(updates) whatever is typed in the box adjacent to it. Coming from a Java world and Spring MVC background, it makes perfect sense as long as the code is as follows:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Test Angular</title>
<script type="text/javascript" src="angular.min.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="maincontroller.js"></script>
</head>
<body>
<div id="content" ng-app="SampleAngular" ng-controller="MainController">
<input type="text" ng-model="inputVal">{{ inputVal }}
</div>
</body>
</html>
app.js
var app = angular.module('SampleAngular', []);
maincontroller.js
app.controller("MainController", function($scope){
$scope.inputVal = "";
}
);
But, the same thing still works if I have a blank body for the controller i.e.:
maincontroller.js
app.controller("MainController", function($scope){
}
);
I understand that I will not be able to get the value of inputVal in the controller but
a) why does it still work in the view?
b) Clearly, I don't have a corresponding model 'inputVal' as defined in ng-model directive, and there are no errors/warnings - which IMHO - is equivalent to failing silently. Is this how Angular is designed? Is this a potential issue in large apps and will make debugging a nightmare?
Thanks in advance.
The following is from the api documentation for ngModel:
Note: ngModel will try to bind to the property given by evaluating the expression on the current scope. If the property doesn't already exist on this scope, it will be created implicitly and added to the scope.
Whenever a ng-model is used in the view, corresponding model value is created on the scope of the controller. Angular won't be throwing any error in this case, as this is its default behaviour.
$scope.inputVal = "";
is used more like initialisation of the variable being used.
Related
I'm new on Angular, I'd like to know what's wrong with my code, because the browser shows me this error: Error: [ng:areq] http://errors.angularjs.org/1.4.7/ng/areq?p0=HelloWorldCtrl&p1=not%20a%20function%2C%20got%20undefined
at Error (native)
y el codigo es este:
<!doctype html>
<html ng-app>
<head>
<title>Angular Practice</title>
</head>
<body>
<h1 ng-controller="HelloWorldCtrl">{{helloMessage}}</h1>
<script src="angular.min.js"></script>
<script type="text/javascript">
function HelloWorldCtrl($scope) {
$scope.helloMessage = "Angular Practice";
}
</script>
</body>
</html>
Thanks a lot.
Your HelloWorldCtrl isn't defined.
This is because you're not binding it as an angular module with a controller attached.
ng-controller looks for a definition like this:
angular.module('HelloWorldCtrl', [])
.controller('HelloWorldCtrl', function($scope){
$scope.helloMessage = "Angular Practice";
});
That controller also needs to be assigned to the main app, which you need to reference on that ng-app directive, i.e.
<html ng-app="helloWorldApp">
Which should point to a module you create as such:
var helloWorldApp = angular.module('helloWorldApp ', [
'HelloWorldCtrl'
])
Notice, I'm including a 'HelloWorldCtrl' reference as an item for the second parameter on that module definition. This tells angular to load that controller as a resource which you can then reference through that ng-controller directive.
EDIT:
Did a little research on my mention of adding 'HelloWorldCtrl' as an item in the array above and wanted to elaborate a little bit on why my solution is slightly different than the other answer here. The way I've set it up, is such that 'HelloWorldCtrl' is a separate module. In this case you do need to reference it in the way I have. This tells the app module that it depends on the 'HelloWorldCtrl' module. In the answer below mine is binding that controller directly to the app, in which case this isn't necessary.
Steps to make it working,
Add a ng-app directive to your <html> tag
Define your module app in the script below.
Define your controller HelloWorldCtrl as below.
Check this Plunker - http://plnkr.co/edit/w8RWm6nr1WgvhX3BbGUE?p=preview
!DOCTYPE html>
<html ng-app="app">
<head>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.0-beta.4/angular.min.js"></script>
</head>
<h1 ng-controller="HelloWorldCtrl">{{helloMessage}}</h1>
<script type="text/javascript">
angular.module('app', []);
angular.module('app').controller('HelloWorldCtrl', [ '$scope', function($scope) {
$scope.helloMessage = "Angular Practice";
}]);
</script>
</html>
I am currently doing the egghead.io AngularJS course and have run into an issue a few others seem to have.
Any solutions I have come across here aren't working for me though.
In the second video the instructor is showing how to connect controllers to ng-apps. I have followed the video exactly, restarted a few times, and tried solutions on here.
I am given the following error console:
In the long list of errors there, I have picked out the first as as saying:
"FirstCtrl' is not a function, got undefined"
Anyone know of a solution?
Was something changed in the Angular spec in regards to assigning controllers, or is this course skipping information?
Code:
function FirstCtrl($scope) {
$scope.data = {
message: "Hello"
};
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Angular App</title>
<link href='https://fonts.googleapis.com/css?family=Roboto|Roboto+Condensed:700' rel='stylesheet' type='text/css'>
</head>
<body>
<div ng-app="">
<div ng-controller="FirstCtrl">
<h1>You said:</h1>
<h3>{{data.message}}</h3>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
</body>
</html>
Here is your exemple working (Run the exemple ...).
Add you app name.
Declare your controller using angular.controller.
angular.module('myApp', []);
angular.module('myApp').controller('FirstCtrl', FirstCtrl);
function FirstCtrl($scope) {
$scope.data = {
message: "Hello"
};
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Angular App</title>
<link href='https://fonts.googleapis.com/css?family=Roboto|Roboto+Condensed:700' rel='stylesheet' type='text/css'>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="FirstCtrl">
<h1>You said:</h1>
<h3>{{data.message}}</h3>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
</body>
</html>
An Angular controller is defined like this :
var app = angular.module('myApp',[]); //Your app
//The controller in the myApp module, first param is the controller's name
//Second is the controller's dependencies
app.controller('FirstCtrl', ['$scope', function($scope) {
//Do whatever you want in this controller
$scope.data.message = 'Hello!';
}]);
Then you bind your controller to the view (your HTML) using the ng-controller attribute.
You're missing the part where you define your controller.
You can definitely have your FirstCtrl be a function. You just need to first define that the FirstCtrl is a controller.
Example:
angular.module("app").controller("FirstCtrl", FirstCtrl);
And then you have your FirstCtrl function:
function FirstCtrl($scope) {
$scope.data = {
message: "Hello"
};
}
You also need to include that file in your html scripts
<script src="mypath/firstctrl.js"></script>
I too was facing problem when defined controller just like a simple JavaScript function and then I downgraded the cdn link version for angular from "1.4.5" to "1.2.28" and it started recognising controller (A simple javascript function). Also you have to include the .js file in which you have created your controller in your html file . Actually they have deprecated the use of simple javascript function as a controller from angular 1.3 version.
When there is a line of code in an Angular application that causes an error, the entire template is broken.
For example, this code (which results in an error when we try to assign a value to foo.bar):
<!doctype html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<title>My App</title>
</head>
<body>
<div class="container" id="home" ng-controller="MainCtrl">
<h1>Message: {{hello_msg}}</h1>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.10/angular.js"></script>
<script>
var myApp = angular.module('myApp', ['myApp.controllers']);
angular.module('myApp.controllers', []).
controller('MainCtrl', ['$scope', function ($scope) {
var hello_msg = 'Hello!';
$scope.hello_msg = hello_msg;
// malformed JS
foo.bar = 'app breaks';
}]);
</script>
</body>
</html>
Completely breaks the page, and it looks like this:
Is there some configuration option that I can add to my Angular app so that the page erorrs out more gracefully? Specifically, the variables in the templates that are wrapped in {{ and }}, do not display them at all if there is an error in the app.
One way to error out more gracefully would be to use:
<div ng-bind-html="hello_msg">
The ugly {{hello_msg}} would not display when the foo.bar breaks the app.
Please check this plunker that proves the point
IMPORTANT NOTE
To use ng-bind-html instead of the curly brackets, you need to include ng-sanitize in your module.
However after writing up a few examples to play around with the controllers would not load. I was getting an error:
firstController is not a function
After some googling I found that Angular 1.3.x no longer supports global controllers. All the examples I have seen of the new way of creating controllers seem to create them in my app.js file. I am confused, does this now mean that I must create all my controllers here rather than having a dedicated file for each controller. I have tried this to create the controller and still no luck:
UPDATE: I changed my controller to match jedanput's answer but changed $scope to this.
app.controller('firstController', [function(){
this.name = "Tim";
}]);
Also I find it very annoying that all that the majority of the example out there still reference the way it was done in Angular 1.2.
Any help would be greatly appreciated as I am having trouble understanding this issue.
EDIT: Here is my index.html file. Hopefully this will help you guys understand what is going wrong.
<!DOCTYPE html>
<html lang="en" xmlns:ng="http://angularjs.org" id="ng-app" ng-app="myApp">
<head >
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ControllerAs</title>
<meta name="description" content="">
</head>
<body>
<div class="content" ng-view=""></div>
<!-- jQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- AngularJS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular-route.js"></script>
<script type="text/javascript" src="../js/app.js"></script>
<!--Directives-->
<script type="text/javascript" src="../js/directives/it-works.js"> </script>
<!--Controllers-->
<script type="text/javascript" src="../js/controllers/firstController.js"></script>
<script type="text/javascript" src="../js/controllers/secondController.js"></script>
</body>
</html>
So far I have avoided Controllers as everything I have been doing could be done with directives and services but it is time I understood more about controllers. I think it may be something fundamental I am missing. Again any help is greatly appreciated.
UPDATE: still getting the same error. This is my app.js file. Maybe it can shed some light on the problem.
var app = angular.module('myApp',[
'ngRoute'
]);
app.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: "../partials/test-skeleton.html"
})
});
It should be
app.controller('firstController', ['$scope', function($scope){
$scope.name = "Tim";
}]);
Also, controllerAs syntax is synthetic sugar for the scope simply, you avoid using this:
<div ng-controller="oneCtrl">
{{name}}
</div>
And instead use this:
<div ng-controller="oneCtrl as one">
{{one.name}}
</div>
Which helps tremendously when you have nested controllers.
You're right, Angular allows for multiple different notations and that can be annoying and confusing. I would recommend you to stick with the guidelines from John Papas Angular Style Guide. He uses this:
(function() {
'use strict';
// Get reference to your application
angular.module('myapp')
// Add the controller
.controller('mycontroller',controller);
// This makes the injection of the controller arguments
// explicit
controller.$inject = ['$scope', '$http'];
// Here the actual controller is defined - where
// the arguments are injected on the same location as
// in the previous array
function controller($scope, $http) {
// Controller logic
});
})();
You want to keep stuff out of the global space. Really - you do. That's why he wraps everything in an Immediately-Invoked Function Expression (IIFE).
Also - you want to explicitly define what you're injecting ( the $inject array ). If not, you will not be able to minify later.
So I'm sorry - I just added another way of defining your AngularJS artefacts. From what I understand, this is one the more well known style guides out there. I've heard that he's working closely with the Angular guys to make sure his style guide will also make it easier to transition to the new Angular version.
And no - you do not need to put everything in 1 file - just make sure you have a file with angular.module('myapp',[]) loaded before any of the other files. This will declare the myapp module and will append the controller to it.
As I'm writing this - I realize that there's also another way: you create a new module in this file, append the controller and then load that module into your application. But yeah ... it's confusing.
I am new to angularjs and this might sound very silly but I want to know why my angularjs app won't bootstrap without making a module even though egghead.io and several tutorials showing otherwise.
Here is my HTML template
<!DOCTYPE html>
<html ng-app>
<head>
<script data-require="angular.js#*" data-semver="1.4.0-beta.1" src="https://code.angularjs.org/1.4.0-beta.1/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
<script src="controller.js"></script>
</head>
<body>
<div ng-controller="HelloController">
<p>{{greeting.text}}, World</p>
</div>
</body>
</html>
And the controller.js file which DOESN'T WORKS
function HelloController($scope) {
$scope.greeting = { text: 'Hello' };
}
When i register the module [and naming the ng-app as 'hello' ofcourse] and write a controller it works
angular.module('hello', []).controller('HelloController', function($scope) {
$scope.greeting = { text: 'Hello' };
});
I just want to know the reason for this behavior.
Thanks in anticipation.
This is a breaking change of angular 1.3. You can see a list of breaking changes here
Because of this change, you cannot use global functions as a controller. You can override this behavior by using allowGlobals (More info here) but I won't recommend that.