AngularJS Uncaught ReferenceError: controller is not defined from module - angularjs

I have the following code;
var app =
angular.
module("myApp",[]).
config(function($routeProvider, $locationProvider) {
$routeProvider.when('/someplace', {
templateUrl: 'sometemplate.html',
controller: SomeControl
});
// configure html5 to get links working on jsfiddle
$locationProvider.html5Mode(true);
});
app.controller('SomeControl', ...);
I get the following error
Uncaught ReferenceError: SomeControl is not defined from myApp
Is the problem just that I can not use app.controller('SomeControl', ...) syntax? when using $routeProvider? is the only working syntax:
function SomeControl(...)

Use quotes:
controller: 'SomeControl'

Like Foo L said, you need to put quotes around SomeControl. If you don't use quotes, you are referring to the variable SomeControl, which is undefined because you did not use a named function to represent the controller.
When you use the alternative that you mentioned, function SomeControl(...), you define that named function. Otherwise, Angular needs to know that it needs to look up the controller in the myApp module.
Using the app.controller('SomeControl', ...) syntax is better because it does not pollute the global namespace.

The above answers are correct however, this error can also happen :
If the name of the controller in you html or jsp etc page is not matching the actual cotnroller
<div ng-controller="yourControllerName as vm">
Also if the name of the function controller does not match the controller definition then this error can happen too.
angular.module('smart.admin.vip')
.controller('yourController', yourController);
function yourController($scope, gridSelections, gridCreationService, adminVipService) {
var vm = this;
activate();

Related

Angular Initialization errors in app.js

So I am trying to jump on the Angular bandwagon, and I have been tasked with building an SPA, for which I have selected AngularJS with ASP.Net MVC Web API (I am a .Net developer). As a fan of strongly typed languages, I have avoided javascript whenever possible throughout my career, but frameworks like AngularJS and the other libraries & plugins in recent years have made it impossible to ignore. So here I am, asking for some guidance.
I have watched the tutorials, done the sample code projects and done some learning on PluralSight, and I have things working, at least from a foundational perspective. I have a rich background in MVVM and MVC, so SOC is a big thing for me. I like the MVC type of structure that Angular provides, which is largely why I went this route in the first place.
Now let me get to my issue(s). I am initializing my module (currently) in my master page (_Layout.cshtml), which I did while tweaking and experimenting, for the sake of simplicity.
<script>
angular.module('xcmApp', ['ngRoute', 'ngResource'])
.config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'companiesController',
templateUrl: 'views/companylist.html'
})
.when('/Reports',
{
controller: 'reportsController',
templateUrl: 'views/reportlist.html'
})
.otherwise({ redirectTo: '/' })
})
.factory('companiesFactory', ['$resource',
function ($resource) {
return $resource('/api/companies', {}, {
query: { method: 'GET', params: {}, isArray: true }
});
}
])
.controller('companiesController', function ($scope, companiesFactory) {
$scope.Companies = companiesFactory.query();
});
</script>
But now that I am ready to move on to deeper concepts, I want to break my scripts out into their appropriate files. Namely, app.js and associated controllers/factories/services etc. However when I move that script into app.js and reference it in _Layout.cshtml, it errors:
<script src="~/app.js"></script>
Error: [$injector:unpr] Unknown provider: a
Now there's no point in continuing to break out into controller files etc. when I can't even get the app.js to work right, so here I am stuck. I know there are some brilliant AngularJS devs on here that probably know what I'm missing before even reading this far, and I am grateful for your assistance.
Anyone who can highlight my oversight will be a superstar for me today. Thanks in advance!
EDIT:
Here is my Stack Trace:
0x800a139e - JavaScript runtime error: [$injector:modulerr] Failed to instantiate module xcmApp due to:
Error: [$injector:unpr] Unknown provider: a
http://errors.angularjs.org/1.3.15/$injector/unpr?p0=a
at Anonymous function (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4015:13)
at getService (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4162:11)
at invoke (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4191:9)
at runInvokeQueue (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4109:11)
at Anonymous function (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4118:11)
at forEach (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:323:11)
at loadModules (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4099:5)
at createInjector (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:4025:3)
at doBootstrap (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:1452:5)
at bootstrap (http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js:1473:5)
http://errors.angularjs.org/1.3.15/$injector/modulerr?p0=xcmApp&p1=Error%3A%20%5B%24injector%3Aunpr%5D%20Unknown%20provider%3A%20a%0Ahttp%3A%2F%2Ferrors.angularjs.org%2F1.3.15%2F%24injector%2Funpr%3Fp0%3Da%0A%20%20%20at%20Anonymous%20function%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4015%3A13)%0A%20%20%20at%20getService%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4162%3A11)%0A%20%20%20at%20invoke%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4191%3A9)%0A%20%20%20at%20runInvokeQueue%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4109%3A11)%0A%20%20%20at%20Anonymous%20function%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4118%3A11)%0A%20%20%20at%20forEach%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A323%3A11)%0A%20%20%20at%20loadModules%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4099%3A5)%0A%20%20%20at%20createInjector%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A4025%3A3)%0A%20%20%20at%20doBootstrap%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A1452%3A5)%0A%20%20%20at%20bootstrap%20(http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.3.15%2Fangular.js%3A1473%3A5)
REMINDER:
My problem is not that it doesn't work, it DOES WORK. It just STOPS working when I take the Javascript out of my HTML page and place it into a referenced app.js file.
Go back to the documentation. You are using a bad way of defining your application. Try:
var MyApp = angular.module( 'MyApp', ['ngRoute' , 'ngSanitize']) ;
and then use MyApp to add controllers, filters, etc.
EDIT:
BTW, it is a good practice to write the Javascripts in separate files for SPA (you are not writing a small project I guess).
It looks like you are missing a few declaration pieces related to Dependency Injection in your controller definition.
Before I post the specific code and fixes, I want to mention a useful troubleshooting tool for Dependency Injection issues. Angular has a built in directive ng-strict-di. This directive is a companion to ng-app. From the ng-app documentation:
if this attribute is present on the app element, the injector will be created in "strict-di" mode. This means that the application will fail to invoke functions which do not use explicit function annotation (and are thus unsuitable for minification), as described in the Dependency Injection guide, and useful debugging info will assist in tracking down the root of these bugs.
Now, to the code in your post:
Your controller is not using explicit function annotation. In explicit function annotation, you pass a string array of dependencies, followed by the function. This ensures that even if minification were to rename the function parameters, Angular can still identify which dependency to supply to the function. You have used explicit annotation in parts of your code, but it is missing from your controller definition.
This is classically easy to identify, with Error: [$injector:unpr] Unknown provider: a, even though you never defined a provider named a. ng-strict-di would flag this controller code.
Here is the current code, and the proposed fix.
Instead of:
.controller('companiesController', function ($scope, companiesFactory) {
Try:
.controller('companiesController', ['$scope', 'companiesFactory', function ($scope, companiesFactory) {
I don't have an ASP.net background, but I think that souldn't matter to answer your Angular question.
First declare your modules like this:
angular.module('myModule', []);
and get them im oder files like this:
angular.module('myModule').controller/foactory/....
So your code should look something like this:
//xcmApp.module.js
angular.module('xcmApp', ['ngRoute', 'ngResource']);
//xcmApp.config.js
angular.module('xcmApp').config(function ($routeProvider) {
$routeProvider
.when('/',
{
controller: 'companiesController',
templateUrl: 'views/companylist.html'
})
.when('/Reports',
{
controller: 'reportsController',
templateUrl: 'views/reportlist.html'
})
.otherwise({redirectTo: '/'})
});
//xcmApp.factory.js
angular.module('xcmApp').factory('companiesFactory', ['$resource',
function ($resource) {
return $resource('/api/companies', {}, {
query: {method: 'GET', params: {}, isArray: true}
});
}
]);
//xcmApp.controller.js
angular.module('xcmApp').controller('companiesController', function ($scope, companiesFactory) {
$scope.Companies = companiesFactory.query();
});
EDIT:
Regarding the error, keep in mind that your dependencies must be in the rigth order.
So your index.html (assuming you use don't use a script loader yet) should look like this:
<script src="/*path to angular*/"></script>
<script src="/*path to ngRoute*/"></script>
<script src="/*path to ngResource*/"></script>
<script src="/*path to xcmApp.module.js*/"></script> //setting your app module must come first
<script src="/*path to xcmApp.config.js*/"></script>
<script src="/*path to xcmApp.factory.js*/"></script> //must come before the controller in your case
<script src="/*path to xcmApp.controller.js*/"></script>

Get module and controller|service|directive names at runtime

Over at angular-logger, we are trying to enhance $log, but we would like to work in the name of the angular's module and component without changes. To do so we need to get the AngularJS context at runtime, that is, the module name and controller, service or directive names.
app.module("SampleModule").
controller("ControllerOne", function ($log) {
$log.debug("I am ready!")
}).
controller("ControllerTwo", function ($log) {
$log.debug("I am ready!")
});
Default $log output:
> I am ready!
> I am ready!
If we can obtain the module and controller name at runtime, then using the enhanced $log we can get richer output:
> SampleModule.ControllerOne: I am ready!
> SampleModule.ControllerTwo: I am ready!
The best option will be to get it without changes to the controller's code. Perhaps there is way to get some meta info about the entities that received the $log dependency injection?
Any suggestions?
There was a similar question that I found on SO, but the solution works only when using controller as syntax.
// a simple route with controller as syntax
$routeProvider.when(
'/myRoute',
{
templateUrl: '/myRoute',
controller: 'ControllerOne as vm'
}
);
// controller
app.controller("ControllerOne", ['$log', function ControllerOne($log) {
var vm = this;
$log.log(vm.constructor.name);
}]);

AngularJS 1.x custom filter can't be injected, unknown provider

I'm trying to create a custom filter, but when I try to inject it into my controller, I get an 'Unknown provider' error. I have checked and double checked all the references, but I can't see what's wrong.
I know that the file is referenced in my index.html correctly, it is loaded and can be found by the inspector. This is the code I have:
In my app.js:
angular.module('equiclass', ['equiclass.controllers',
'equiclass.services',
'ngRoute'])
.config(function ($routeProvider) {
$routeProvider
.when('/courses', {
templateUrl: 'views/courses.html',
controller: 'CourseCtrl'
// And some other stuff with routes
});
angular.module('equiclass.controllers', ['equiclass.services', 'equiclass.filters']);
angular.module('equiclass.services', []);
angular.module('equiclass.filters', []);
My filter:
angular.module('equiclass.filters')
.filter('testFilter', function() {
return function(input) {
return undefined;
};
});
And the controller:
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope, testFilter) {
});
Of course this is quite simplified, but it just doesn't work, and I can't see why. I have made several services and they all work and play along nicely.
If you want to use filter inside a controller you have to inject $filter attribute to your controller and can access it like
$filter('filtername');
You can use like
function myCtrl($scope, $filter)
{
$filter('filtername')(arg1,arg2);
}
You don't need to inject the filter itself.
This code...
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope, testFilter) {
});
Should be
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope) {
});
And inside CourseCtrl you should use your filter as you normally do.
Injecting the module 'equiclass.filters' into your module 'equiclass.controllers' is enough.
I had a similar issue and made a post about it on my blog.
--Edit
As n00dl3 mentions below the tricky part is how the auto-naming convention works in Angular. If you name your filter specialNumberFilter then when you inject it you need to refer to it as specialNumberFilterFilter. This allows you to use the filter as a function, which is what it is.
// In a controller
vm.data = specialNumberFilterFilter(vm.data, 'a');
But I believe you can also use the filter without injecting it into a controller if it is used in a string expression that is being evaluated by, say, a watch because this would be the same as the scenario when you are using it in a template.
// Inside a watch - no controller injection required
`$scope.$watch('vm.data | specialNumberFilter', function(new, old) { ... })`
According to Angular's documentation :
if you want to use your filter in a template
then you just need to inject it in your module and then use it like this {{ expression | filter }} or {{ expression | filter:argument1:argument2:... }} .
doc
if you want to use your filter in a controller, directive, and stuffs :
inject a dependency with the name <filterName>Filter, like this :
controller('MyController', ['filterFilter', function(filterFilter) {}]);
doc
so for this particular case :
angular.module('equiclass.controllers')
.controller('CourseCtrl', function ($scope, testFilterFilter) {
});
you didn't mention if it's in production or on a local server, but just in case you are minifying your files, try this:
angular.module('equiclass.controllers')
.controller('CourseCtrl', ['$scope', 'testFilter', function ($scope, testFilter) {
}]);

Passing javascript variables from controller to partial file in AngularJs

I am new to AngularJs. I have put a url value in the scope variable inside a controller. This value should be used in the partial file corresponding to the controller inside a javascript function. How can I achieve this in AngularJs.
Code snippet is given below for reference:
Config code:
myApp.config(function ($routeProvider){
$routeProvider.
when('/state-details/:id',
{
controller:'controllers.StateDetailsCtrl',
templateUrl:'/partials/state-details.html'
})
.... More routes defined below...
Inside the controller:
controllers.StateDetailsCtrl= function($scope, $routeParams, $http){
$scope.testURL='http://www.google.com'
.... More values set in the scope..
Inside the state-details partial file:
<script>
// how to get the value of the testURL defined in the scope?
</script>
Please let me know how to get this working?
If you need to add additional javascript into a partial html file, then it just like screams to use a directive.
There you can inherit the whole ctrl scope or create a isolated scope.
https://docs.angularjs.org/guide/directive

Using AngularJS Controllers created with angular.module().controller()

I am still very new to AngularJS and am working through setting up my first application. I would like to be able to do the following:
angular.module('App.controllers', [])
.controller('home', function () {
$scope.property = true;
}]);
angular.module('App', ['App.controllers'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {templateUrl: 'partials/home.html', controller: home});
}]);
Using this setup the following error is generated:
Uncaught ReferenceError: home is not defined from App
My question is: How can I register controllers using angular.module.controller() (or $controllerProvider.register() directly) and use the registered controller elsewhere in my app.
My motivation: I would like to avoid using either global constructor functions as my controllers (as most of the examples on angularjs.org use) or complex namespacing. If I can register and use controllers as single variable names (that are not then put in the global scope) that would be ideal.
Try using a string identifier.
routeProvider.when('/', {templateUrl: 'partials/home.html', controller: 'home'});
When you use a literal, it is looking for a variable called home, but that doesn't exist in this case.
If you are getting controller is not defined error you have to write your controller name within the quotes.
or define your controller like this
function controllerName()
{
//your code here
}
refer this: Uncaught ReferenceError:Controller is not defined in AngularJS

Resources