Hullo everyone, I am having a problem with AngularJs not reconizing my controller, I have summarised what I have done below.
Starting point: AngularJs tutorial http://www.thinkster.io/angularjs/ZPCQtVfGba/angularjs-controllers
Problem:
defined controller in file (gets retrieved correctly when visiting page), added ng-controller directive to relevant div, got javascript runtime error (
Error: [ng:areq] http://errors.angularjs.org/1.3.0-beta.18/ng/areq?p0=FirstCtrl&p1=not%20a%20function%2C%20got%20undefined
)
Before posting I checked whether I had included my controller implementation before including Angular but it is not the case.
What am I missing? I suspect it might have something to do with declaring controllers in the global scope (e.g. Controller not a function, got undefined, while defining controllers globally) but I am not really sure whether this is indeed the case.
Thanks in advance!
_Layout .cshtml
<!DOCTYPE html>
<html ng-app>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#RenderSection("PageSpecificStyles",required:false)
</head>
<body>
#RenderBody()
#RenderSection("BodyScripts", required: false)
</body>
</html>
Index.cshtml:
#{
ViewBag.Title = "Home Page";
}
#section PageSpecificStyles{
<style>
div {
margin-left: 20%;
}
</style>
}
#section BodyScripts{
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.18/angular.min.js"></script>
<script src="~/Scripts/FirstCtrl.js"></script>
}
<div ng-controller="FirstCtrl">
<div>
<h1>Hello {{data.message}}</h1>
</div>
</div>
FirstCtrl.js (in ~/scripts)
function FirstCtrl($scope) {
$scope.data = { message: "Cat!" };
}
As you suspected, since you are using angular 1.3 beta which has no implicit support for Global controller constructor function discovery, you need to register your controller with the module.
angular.module('yourApp').controller('FirstCtrl',['$scope', FirstCtrl]);
and also since you are defining an module you need to specify the module name in your ng-app.
<html ng-app="yourApp">
Related
I am trying to get AngularJS 1.5.9 up and running an MVC 5 application using a very simple component called configuration-list.
I created an MVC 5 application (4.5.2), added the Angular.Core 1.5.9 Nuget package
To take MVC 5, layout and razor rendering out of the picture, I created a simple file called test.htm:
<!DOCTYPE html>
<html ng-app>
<head>
<title></title>
<meta charset="utf-8" />
<script src="Scripts/angular.js"></script>
<script src="Scripts/app/module.js"></script>
</head>
<body>
<configuration-list></configuration-list>
</body>
</html>
And in module.js:
(function () {
"use strict";
angular.module("radar", []).component("configuration-list", {
template: "Hello from configuration list"
});
}());
The browser (IE 11) comes up empty.
I have opened the debugging tools and go to the console tab, and there are no errors logged.
I have put a breakpoint in module.js and it is hit (so I know the code is running)
I have tried moving the scripts below the component in the body tag
I have tried setting ng-app="radar" in the html tag
Any idea what I'm missing?
For components the naming has to be camelcase, not hyphencase
angular.module("radar", []).component("configurationList", {
template: "Hello from configuration list"
});
I'm trying to make an SPA website with knockout and requirejs from websites I've seen and tutorials, in order to split up the website so it isn't a single gigantic thing. At one point I'm expecting to see:
My first name is: Bryan
But instead I'm getting:
My first name is: function c(){if(0<arguments.length)return c.tb(c[E],arguments[0])&&(c.ga(),c[E]=arguments[0],c.fa()),this;a.l.oc(c);return c[E]}
Starting with my index.thml:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>asdf</title>
</head>
<body>
<mainview></mainview>
<!-- global imports -->
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.min.js"></script>
<script type='text/javascript' src="./index.js"></script>
</body>
</html>
My index.js:
"use strict";
requirejs.config({
baseUrl: '',
paths: {
knockout: 'https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min',
text: 'https://cdnjs.cloudflare.com/ajax/libs/require-text/2.0.12/text.min'
}
});
ko.components.register(
'mainview',
{
require: './indexViewModel'
}
);
ko.applyBindings();
indexViewModel.js:
"use strict";
define(['knockout', 'text!./indexViewModel.html'], function(ko, htmlString) {
function indexViewModel(params)
{
var self = this;
self.firstName = ko.observable('Bryan');
}
return { viewModel: indexViewModel, template: htmlString };
});
Finally my indexViewModel.html:
<div>
<p>input name: <input data-bind="value: firstName"></input></p>
<p>My first name is: <span data-bind='text: firstName'></span></p>
</div>
All this gives the result I stated above.
Now if I change firstname to firstName(), then it initially comes up right, but if I change the input, nothing happens.
ok, with more digging and googling, I happened upon the solution. I don't get the details, but it's requirejs and knockoutjs are colliding some how
Because on my index.html, I import knockout and I have knockout setup as a requirejs parameter from the config.
I found this
Issue loading knockout components view model using requireJS
that clued me in.
ok so I made these changes:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Battlestations Character Generator</title>
</head>
<body>
<mainview></mainview>
<!-- global imports -->
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.22/require.min.js"></script>
<!-- no more knockout reference here -->
<script type='text/javascript' src="./index.js"></script>
</body>
</html>
now my index.js:
"use strict";
requirejs.config({
baseUrl: '',
paths: {
knockout: 'https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min',
text: 'https://cdnjs.cloudflare.com/ajax/libs/require-text/2.0.12/text.min'
}
});
// "app main()"
requirejs(['knockout'], function(ko) {
var self = this;
ko.components.register(
'mainview',
{
require: './indexViewModel'
}
);
ko.applyBindings();
});
and changed <input></input> to <input />, although that changed nothing, but if that's "good practice", I'll go with it.
after those changes, reload, all works, and changing the input changes the <span> right after it.
yay!
I know an answer is accepted, Here I am posting an answer just for the users who have tried the answer and failed. I was also experiencing this issue in my MVC application. The problem was, I was referring the knockout-3.4.0.js file both in _Layout.cshtml and the my page. When I remove the JS reference from _Layout.cshtml and reference the same to only to the page, it was all fine. Cheers!
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.
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.