i know this question has already been asked, but i could not find the answer to my personal case. I'm sure it's a stupid thing i didn't notice but i'm not getting out of it.
I'll post all the code i have (it's not that much) because i can not find the real origin of the error.
This is my app.js file:
'use strict';
var myApp = angular.module('myApp', [
'ngRoute',
'appControllers'
]);
myApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/faq', {
templateUrl: 'faq/faq.html',
controller: 'FaqCtrl'
}).
when('/log', {
templateUrl: 'log/log.html',
controller: 'LogCtrl'
}).
[...]
when('/settings', {
templateUrl: 'settings/settings.html',
controller: 'SettingsCtrl'
}).
otherwise({redirectTo: '/homepage'});
}]);
While here is where i hold my controllers, controllers.js:
'use strict';
/* Controllers */
var appControllers = angular.module('appControllers', []);
appControllers.controller('FaqCtrl', [function() {
}]);
appControllers.controller('HomepageCtrl', [function() {
}]);
[...]
appControllers.controller('SettingsCtrl', function($scope, $http) {
/*
$scope.myData = {};
$scope.myData = function(item, event) {
var response = $http.get("myURL");
response.success(function() {
alert("ok");
});
response.error(function() {
alert("error");
});
*/
});
And here is settings.html:
<div ng-controller="SettingsController" >
<button ng-click="myData.doClick(item, $event)">Send AJAX Request</button>
<br/>
Data from server: {{myData.fromServer}}
</div>
Now, if i run it with the code inside SettingsCtrl commented it works fine, but if i decomment it, the page does not end its loading (even if i don't go to the Settings section) and the error is this:
Error: [$injector:modulerr] Failed to instantiate module myApp due to:
[$injector:modulerr] Failed to instantiate module appControllers due to:
[$injector:nomod] Module 'appControllers' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
What did i miss?
I'm sure it will be a stupid thing, but i'm a newbie with AngularJS.
Thanks in advance.
When you uncomment the curly braces are not closed properly.
appControllers.controller('SettingsController', function($scope, $http) {
$scope.myData = {};
$scope.myData = function(item, event) {
var response = $http.get("myURL");
response.success(function() {
alert("ok");
});
response.error(function() {
alert("error");
});
}
});
http://plnkr.co/edit/4sltz2Bwai9zm9FLkyC7?p=preview
One more issue, the controller name is not matching but you probably have figured it out already.
Looks like you didn't include the controller file in your index.html
you lost a "}"
appControllers.controller('SettingsCtrl', function($scope, $http) {
$scope.myData = {};
$scope.myData = function(item, event) {
var response = $http.get("myURL");
response.success(function() {
alert("ok");
});
response.error(function() {
alert("error");
});
}
});
Related
i'm working with angular-seed project.
I'm trying to retreive data from mysql database.
I need to know how to define different controller for each view.
For example, I have this structure:
js
|_modules
|_companies
|_controller.js
|_data.js
|_app.js
|_base.js
I have added this route to app.js
.state('app.companies', {
url: '/companies',
title: 'Companies',
templateUrl: helper.basepath('companies.html'),
controller: 'companiesCtrl' //THIS THROWS THE ERROR BELOW
})
companies.html has scripts added to botom of the page
<script src="app/js/modules/companies/data.js"></script>
<script src="app/js/modules/companies/controller.js"></script>
and this is the code for controller.js (also tested the commented part)
(function() {
'use strict';
angular
.module('appname')
.controller('companiesCtrl', companiesCtrl);
companiesCtrl.$inject = ['$scope','companiesData','$log'];
function companiesCtrl($scope, companiesData, $log) {
console.log('asd'); //NEVER REACH THIS LOG
};
});
/*var app = angular
.module('appname')
.controller('companiesCtrl', ['$scope','companiesData','$log', function($scope, companiesData, $log){
console.log('asd'); //NEVER REACH THIS LOG
$scope.companies = {};
Data.get('companies').then(function(data){
$scope.companies = data.data;
console.log('($scope.companies)');
});
}]);
*/
But I keep getting
Error: [ng:areq] Argument 'companiesCtrl' is not a function, got undefined
Same if I script ng-controller="companiesCtrl" on my view.
change your function to:
(function() {
'use strict';
angular
.module('appname')
.controller('companiesCtrl', companiesCtrl);
companiesCtrl.$inject = ['$scope','companiesData','$log'];
function companiesCtrl($scope, companiesData, $log) {
console.log('asd'); //NEVER REACH THIS LOG
};
})();// execute this function then it will work
See this example if you remove () breaket then it will give you the error.
If possible then create controller like this:
angular.module('appname')
.controller('companiesCtrl', ['$scope', function($scope) {
console.log('asd'); //NEVER REACH THIS LOG
}]);
Please change your controller as :
(function() {
'use strict';
function companiesCtrl($scope, companiesData, $log) {
console.log('asd'); //NEVER REACH THIS LOG
};
angular
.module('appname')
.controller('companiesCtrl', companiesCtrl);
companiesCtrl.$inject = ['$scope','companiesData','$log'];
})();
The problem was on script loading.
I had to use lazy loading of the files within my app.js
Here's the code:
app.js companies route
.state('app.companies', {
url: '/companies',
title: 'Companies',
templateUrl: helper.basepath('companies.html'),
resolve: helper.resolveFor('companiesCtrl'),
controller: 'companiesCtrl'
})
lazy load code
.constant('APP_REQUIRES', {
scripts: {
'modernizr': ['vendor/modernizr/modernizr.custom.js'],
'icons': ['vendor/fontawesome/css/font-awesome.min.css',
'vendor/simple-line-icons/css/simple-line-icons.css'],
'companiesCtrl': ['app/js/modules/companies/data.js','app/js/modules/companies/controller.js']
},
modules: []
});
I had an angular setup that looked like this:
var dashboard = angular.module('Dashboard', ["ngRoute", "highcharts-ng"]);
dashboard.config(function($routeProvider, $locationProvider){
$routeProvider.when('/route1', {
templateUrl: 'route1.html',
controller: 'DefaultCtrl'
});
})
.controller('DefaultCtrl', function($scope, $rootScope, $http, settings){
function($scope, $rootScope, $http, settings){
$http.get("http://admin.gmserver.net/games/all?userId=" + settings.userId).success(function(data){
$scope.games = data;
$rootScope.gameId = "";
$rootScope.gameName = "";
$rootScope.apiName = "";
$rootScope.$broadcast("loaded");
});
}
})
And this worked. I then tried to split them up into multiple files (one for each controller), and now it looks like this:
module file:
angular.module('Dashboard', ["ngRoute", "highcharts-ng"]);
angular.module('Dashboard').config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider){
$routeProvider.when('/route1', {
templateUrl: 'route1.html',
controller: 'DefaultCtrl'
});
}
])
controller file:
angular.module('Dashboard').controller("DefaultCtrl", ['$scope', '$rootScope', '$http', 'settings',
function($scope, $rootScope, $http, settings){
$http.get("http://admin.gmserver.net/games/all?userId=" + settings.userId).success(function(data){
$scope.games = data;
$rootScope.gameId = "";
$rootScope.gameName = "";
$rootScope.apiName = "";
$rootScope.$broadcast("loaded");
});
}
]);
Now when I load the page I get this:
I am loading the files like this:
<script src="http://code.highcharts.com/adapters/standalone-framework.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="/media/js/highcharts-ng.min.js"></script>
<!-- Begin app code -->
<script src="/admin/Dashboard.js"></script>
<!-- Built with smarty -->
<script>
angular.module('Dashboard').value("settings", {
userId: "{$userId}",
secret: "{$secret}"
});
</script>
<script src="/admin/components/default/DefaultController.js"></script>
<script src="/admin/components/game/GameController.js"></script>
<script src="/admin/components/leaderboard/LeaderboardController.js"></script>
<script src="/admin/components/newsFeed/NewsFeedController.js"></script>
I do notice that commenting out one of the following stops the Aw, Snap error.
DefaultController.js file
Inline JavaScript
highcharts-ng.min.js file
Edit:
I changed the name of the module to my site's name and made the Dashboard a dependency like this:
angular.module('GMServer', ["ngRoute", "highcharts-ng", "Dashboard"]);
angular.module('Dashboard')
This fixes the "Aw, Snap" issue, but now I get this error: https://docs.angularjs.org/error/$injector/nomod?p0=Dashboard
I'm not entirely sure what happens when you call the same angular.module several times but I would avoid it.
You want to save the module globally so then you can reference it in different files instead of calling angular.module('Dashboard') each time:
window.Dashboard = angular.module('Dashboard', ["ngRoute", "highcharts-ng"]);
window.Dashboard.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider){
$routeProvider.when('/route1', {
templateUrl: 'route1.html',
controller: 'DefaultCtrl'
});
}
])
and
window.Dashboard.controller("DefaultCtrl", ['$scope', '$rootScope', '$http', 'settings',
function($scope, $rootScope, $http, settings){
$http.get("http://admin.gmserver.net/games/all?userId=" + settings.userId).success(function(data){
$scope.games = data;
$rootScope.gameId = "";
$rootScope.gameName = "";
$rootScope.apiName = "";
$rootScope.$broadcast("loaded");
});
}
]);
You'll just need to make sure your <script> tags are included in the correct order.
Avoid polluting the window object though, you may wanna namespace everything under window.App or use someting like requireJS or Browserify.
Edit
It's perfectly safe to retrieve a module like the OP is doing as pointed out #Sunil and documented here
I want to load config file in Angular application, only the first time when application is opened. Then config variables become globally available across the application. Here is what I come up so far in my app.js:
angular
.module('myApp', [
...
])
.run(
[ '$rootScope', '$http',
function ($rootScope, $http) {
$http.get('config/config.json').success(function(data) {
$rootScope.config = data;
});
}
]
)
Here I load the config.js and when I try to use it in my controller like so:
angular.module('myApp')
.controller('MainCtrl', function ($rootScope) {
console.log($rootScope, $rootScope.config);
})
For $rootScope I can see all properties including config, but $rootScope.config returns undefined.
How to load config file on first page load and then make it accessible throughout the app?
Thanks!
As described in Mark Colemans blog post about this, you can get your config and then load the application. Pasting Mark's code for convenience:
var urlToCheck = '/echo/json/';
var myApp = angular.module('myApp', []);
myApp.controller("MyCtrl", ["$scope", "config", function ($scope, config) {
$scope.url = config.url;
}]);
$.ajax({
url: urlToCheck
}).fail(function () {
myApp.constant('config', {
url: '/fail-url'
});
}).done(function () {
myApp.constant('config', {
url: '/done-url'
});
}).always(function () {
angular.bootstrap(document, ['myApp']);
});
You can initialize it to a promise and then access it in the controller when the promise is resolve. reject the promise too.
http://plnkr.co/edit/EIBJhZg80lpeyhkMD3FD
$q.when($rootScope.config).then(function (config) {
console.log($rootScope.config, config);
});
I am trying to lazy load my controllers for my AngularJS app I built along side with requireJS. I have created a custom "lazyLoad" library that creates a resolve object in app.config() routes (also I am using ui-router). If I code the state (without my library) to look like so it works
define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){
var app = angular.module('myApp', ['ui.router']);
app.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {
window.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
$urlRouterProvider.otherwise('/');
$stateProvider
.state('campaigns', {
url:'/campaigns',
views: {
"top-nav" : {
templateUrl: 'views/home/top-nav.html',
resolve : {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require(['../app/controllers/header-controller'], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
}
},
"fullpage": {
templateUrl: 'views/home/index.html',
resolve : {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require(['../app/controllers/home-controller'], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
}
//controller: 'home-controller'
}
}
});
});
return app;
});
If I attempt to replace the resolve object with my library function it looks would look like this:
define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){
and
.state('home', lazyLoader.route({
url:'/',
views: {
"top-nav" : {
templateUrl: 'views/home/top-nav.html',
controllerUrl: '../app/controllers/header-controller'
},
"fullpage": {
templateUrl: 'views/home/index.html',
controllerUrl: '../app/controllers/home-controller'
}
}
}));
lazyLoader.js
define(function () {
'use strict';
function LazyLoader() {}
LazyLoader.prototype.route = function(config){
var controllerPath;
if(config && config.views){
var singleView = Object.keys(config.views);
for(var i in singleView){
var viewName = singleView[i];
controllerPath = config.views[viewName].controllerUrl;
delete config.views.controllerUrl;
config.views[viewName].resolve = {
load : ['$q', '$rootScope', function($q, $rootScope){
var d = $q.defer();
require([controllerPath], function() {
$rootScope.$apply(function(){
d.resolve();
});
});
return d.promise;
}]
};
}
}
return config;
}
return new LazyLoader();
});
Example Controller
define(['app/module'], function (module) {
lazy.controller('header-controller', ['$scope', function ($scope) {
// stuff here
}]);
});
On a side note I plan on implementing something better than attaching lazy variable to window.
When I code the router like the first example it works. When I use my lazyLoader the one of the two views loads it's controller, the second view's controller's file is started to load (console.logs at the beginning show this) but it cannot resolve "module" in the example above.
link to error: AngularJS Error
Again this issue only happens when using my lazyloader which is producing the same resolve object that I have hard coded in for the version that works.
I have searched high and low and there are a lot of resources out there but I could not find anything that addressed this issue.
Any advice is appreciated!
You are taking too much pain to do lazy loading of controllers & services. There is simple approach to lazy load files with ocLazyLoad. This article might help you resolve the same issue.
https://routerabbit.com/blog/convert-angularjs-yeoman-spa-lazyload/
What you should do is
Add a reference of ocLayzLoad & updated JS files’ reference to load on demand from app.js or .html file of their views.
`bower install oclazyload --save-dev`
Now load the module ‘oc.lazyLoad’ in application. Update app.js file
angular
.module('helloWorldApp', [
'ngCookies',
'ngResource',
'ngRoute',
'ngSanitize',
'oc.lazyLoad',
])
Load JS file by adding reference of JS in .html file
<div oc-lazy-load="['scripts/controllers/about.js', 'scripts/services/helloservice.js']">
<div ng-controller="AboutCtrl as about">
Your html goes here
</div>
</div>
If you using Grunt, update Gruntfile to uglyfy, renamed file name & update references in the final .html or .js file.
On the 'myApp' module definition, shouldn't you be returning app variable instead of myApp?
And to avoid exposing lazy to window, you could define it as a property of app variable, this way when you define new functions, you require app first and you can use it:
app.js:
app.lazy = {
controller: $controllerProvider.register,
directive: $compileProvider.register,
filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
};
...
return app;
controller.js:
define(['app'], function (app) {
app.lazy.controller('header-controller', ['$scope', function ($scope) {
// stuff here
}]);
});
I am aware that the error which is in the title of this question is basically because in my controller I am injecting a Session service in my controller that has not been defined. I am currently looking at: Angular Devise for which I am rolling out in an application that is using rails but have angular and rails separate. My setup on the angular side is as followed:
main.js
angular.module('App.controllers', []);
angular.module('App.config', []);
angular.module('App.directives', [])
angular.module('App.resources', ['ngResource']);
angular.module('App.services', []);
var App = angular.module("App", [
"ngResource",
"ngCookies",
"$strap.directives",
"App.services",
"App.directives",
"App.resources",
"App.controllers",
"TotemApp.config"
], function ($routeProvider, $locationProvider, $httpProvider) {
var interceptor = ['$rootScope', '$q', function (scope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status == 401) {
window.location = "/login";
return;
}
return $q.reject(response);
}
return function (promise) {
return promise.then(success, error);
}
}];
});
Session.js
App.service('Session',[ '$cookieStore', 'UserSession', 'UserRegistration', function($cookieStore, UserSession, UserRegistration) {
this.currentUser = function() {
return $cookieStore.get('_angular_devise_user');
}
this.signedIn = function() {
return !!this.currentUser();
}
this.signedOut = function() {
return !this.signedIn();
}
this.userSession = new UserSession( { email:"sample#email.com", password:"password", remember_me:true } );
this.userRegistration = new UserRegistration( { email:"sample#email.com", password:"password", password_confirmation:"password" } );
}]);
sessions_controller
App.controller('SessionsController', ['$scope', '$location', '$cookieStore', 'Session', function($scope, $location, $cookieStore, Session) {
$scope.session = Session.userSession;
$scope.create = function() {
if ( Session.signedOut ) {
$scope.session.$save().success(function(data, status, headers, config) {
$cookieStore.put('_angular_devise_user', Session.userSession.email);
$location.path('/todos');
});
}
};
$scope.destroy = function() {
$cookieStore.remove('_angular_devise_user');
$scope.session.$destroy();
};
}]);
routes.js
'use strict';
App.config(function($routeProvider, $httpProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main/home.html',
controller: 'MainCtrl'
})
.when('/login', {
templateUrl: 'views/sessions/new.html',
controller: 'SessionsController'
})
.when('/sign_up', {
templateUrl: 'views/registrations/new.html',
controller: 'RegistrationsController'
})
.otherwise({
redirectTo: '/'
});
});
This error occurs when I try to access the login page or register page. If someone can shed some light that would be greatly appreciated. Not entirely sure how to resolve this Error: Unknown provider: $SessionProvider <- $Session error
At first glance this looks correct. I can only assume that perhaps you've not included Session.js in your index.html file?
Angular clearly doesn't know what 'Session' service is so there's something wrong there either file not loaded, not loaded correctly or something along those lines as far as I can see.
Edit: Does the error say 'SessionProvider <- Session' or '$SessionProvider -< $session' because if it's the latter, then something is named wrong somewhere in your app since your service is named 'Session' not '$Session'.
When you have syntax error in other javascript or typescript files. You will get the same error. Please make sure that you have no syntax error.