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.
Related
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 want to manage my controller specific to an ng-view page, therefore I put the controller in ng-view page and used that controller specific to that page only. However, the code does not show what it should show from that controller.
Here is my case.
I split my code into 3 files, which are "mainfile.php", "page1file.php", and "page2file.php". "mainfile.php" contains main page which routes to page 1 and page 2. To compare the results, I created different conditions for those 2 pages. "page1file.php" uses controller which has been defined in "mainfile.php", while "page2file.php" uses controller which is defined in the page itself.
In this circumtances, "page1file.php" successfully shows what I want, but "page2file.php" does not show what it should show. Please help me and give a very simple explanation and a simple solution since I'm very new to angularjs.
Here is my code. You can just copy them and run it on your php server.
mainfile.php :
<!DOCTYPE html>
<html>
<head>
<title>learn angular routing</title>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
<script type="text/javascript">
function routeReload($scope) {
$scope.routeReloading = function(){
window.location.reload();
};
}
routeReload.$inject = ['$scope'];
function routeConfig($routeProvider) {
$routeProvider
.when('/one',{
templateUrl:'page1file.php'
})
.when('/two',{
templateUrl:'page2file.php'
})
;
}
routeConfig.$inject=['$routeProvider'];
function testOne($scope) {
$scope.name = "page one";
}
testOne.$inject = ['$scope'];
var testNgView = angular.module('testNgView',['ngRoute']);
testNgView.config(routeConfig);
testNgView.controller('routeReload',routeReload);
testNgView.controller('testOne',testOne);
</script>
</head>
<body>
<div ng-app="testNgView">
<div ng-controller="routeReload">
View page <a ng-click="routeReloading();" href="#one">one</a> or
<a ng-click="routeReloading();" href="#two">two</a>
<div ng-view></div>
</div>
</div>
</body>
</html>
page1file.php :
<div ng-controller="testOne">
This is {{name}}
</div>
page2file.php :
<script type="text/javascript">
function testTwo($scope) {
$scope.name = "page two";
}
testTwo.$inject = ['$scope'];
testNgView.controller('testTwo',testTwo);
</script>
<div ng-controller="testTwo">
This is {{name}}
</div>
I don't think you can inline script modules in your view templates. Have a look at this working version of your app, the way I would organize it:
http://plnkr.co/edit/nSsagK1Y04akNJyMToah?p=preview
You can use .php files in place of the .html files, that shouldn't make a difference.
So your main file should look something like this:
<!DOCTYPE html>
<html>
<head>
<title>learn angular routing</title>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-route.min.js"></script>
</head>
<body>
<div ng-app="testNgView">
View page one
or two
<ng-view></ng-view>
</div>
<script src="app.module.js"></script>
<script src="app.routes.js"></script>
<script src="views/page1/controller.js"></script>
<script src="views/page2/controller.js"></script>
</body>
</html>
If your goal is to use PHP to dynamically render your controllers, see the answer to this SO question: Angularjs: server side (php) rendering and data binding client side after an event
You may also be interested in this article, about loading Angular components after the application has been bootstrapped: http://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm
TL;DR: You would need to store a reference to $controllerProvider in the config phase, and then call $controllerProvider.register('MyController', MyController) in your inline script. I'm not sure how I feel about that though...
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.