I am kind of new to the AngularJS framework and I am trying to migrate my test project using the standard router to use the UI-router, but I get the following error:
Error: [ng:areq] Argument 'mainCtrl' is not a function, got undefined
What I have done so far is:
Controller:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
Router:
angular.module('sm-web', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function( $stateProvider, $urlRouterProvider ) {
$urlRouterProvider.otherwise('root');
$stateProvider
.state('root', {
url: '',
templateUrl: path + 'ng/sm/view/main.html',
controller: 'mainCtrl'
});
}]);
Index:
<body ng-controller="mainCtrl">
<main-menu></main-menu>
<div class="container">
<div ui-view></div>
</div>
</body>
This works when I use the standard router, but not with the UI-router. Does anyone have any idea of what I am doing wrong?
It seems you have an issue w/the order you declare things. For you to declare the module "sm-web" you need to do this:
angular.module('sm-web', ['ui.router']);
Note that the presence of that 2nd array argument is what tells Angular that you're declaring the module (eg. creating a new module). When you leave that 2nd argument out, you're retrieving the module you previously declared.
So with that in mind, look at how it all is coming together in your code:
To declare the controller, you retrieve the module "sm-web" (by leaving off the 2nd array arg).
When configuring the router states, you declare a new module "sm-web". But note that immediately after you declare this new module, you try to register a state with the controller named "mainCtrl" -- but that doesn't exist yet.
You need to create the module somewhere before doing all of the above. After creating the module, then register the controller on the module. Finally, with the controller defined, then you can register the state that uses the controller.
There's too many ways to solve this ordering problem, so I'm not going to suggest anything further. It depends on what files the code lives in and the order you load those files in index.html.
In order to avoid your problem change your code by the following code:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
Related
I have a hard time understanding this. I'm attempting to put controllers in separate files so that they only deal with 1 thing, ideally, a partial view
My folder structure is like this...
My app.js file is like this.
angular.module('mikevarela', ['ui.router', 'mikevarela.controller.home', 'mikevarela.controller.about', 'mikevarela.controller.audio'])
.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: '../partials/home.partial.html',
controller: 'HomeController'
})
.state('about', {
url: '/about',
templateUrl: '../partials/about.partial.html',
controller: 'AboutController'
})
.state('audio', {
url: '/audio',
templateUrl: '../partials/audio.partial.html',
controller: 'AudioController'
});
});
and my controllers each have a module like this...
angular.module('mikevarela.controller.home', [])
.controller('HomeController', ['$scope', function($scope) {
$scope.title = 'Mike Varela Home Page';
}]);
My issues comes with the intial app declaration. I don't want to have to inject all the controllers in the main array app definition, that would be cumbersome and long winded. Isn't there a way to define the controller at the controller file. Kind of like this
angular.module('mikevarela', []).controller('HomeController', ['$scope', function($scope) {
// stuff here
}]);
Use angular.module('mikevarela').controller..... in subsequent files.
angular.module('mikevarela',[]).controller.....
is equivalent to redefining your app. The second param is requires array.
Quoting official angular.module docs
requires
(optional)
!Array.=
If specified then new module is being created. If unspecified then the module is being retrieved for further configuration.
About your Controllers...
I think you're loading the controllers incorrectly.
You don't need to declare controllers as a dependency. Rather stating module.controller('yourController)` makes that controller available throughout the module.
If your controllers are in separate files, all you need to do to make it available is load it in with a script tag. e.g.
<script src="app.js"></script>
<script src="controller1.js"></script>
<script src="controller2.js"></script>
About your Application Structure...
This is not related to your question, but just coming from someone who's developed using Angular, I'd recommend not grouping your application by controllers/ by rather by feature. See: https://scotch.io/tutorials/angularjs-best-practices-directory-structure
Question Background:
I am using AngulaJS's UI Router for the first time to create two views within my app.
The Issue:
Plunker link: https://plnkr.co/edit/2XAKa6mDCUyzyOPz2CNK
I feel I'm missing something simple here but I cannot get any route to render the specified html templates set in the app.js.
Eventually I want the Update.html template to render when the submit fucntion of the home.html (search()) is clicked but first off I need to be able to actually render a single view which I currently cannot.
I would expect on-load for the route to render up the home.html page but it wont:
Any help sorting this will be much appreciated.
app.js:
angular
.module('app', [
'ui.router'
])
.config(['$urlRouterProvider', '$stateProvider', function($urlRouterProvider, $stateProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'home.html',
controller: 'HomeController'
})
.state('update', {
url: '/update',
templateUrl: 'Update.html',
controller: 'UpdateController'
})
}])
Looking at your plunker briefly, it looks like your controller files are creating new angular apps with the same name. They were overriding each other so the .config() block didn't exist in the final app. I have updated the controller files in this plunker and it seems to be rendering the first ui view fine:
https://plnkr.co/edit/cdpWWOaBJWL3dONtIXzv?p=preview
Notice in the controller files, the angular.module('app') no longer has the second argument ['ui-bootstrap'] which was causing a new angular app to be created for each controller file. Check it out here in the angular docs.
Beware that using angular.module('myModule', []) will create the module myModule and overwrite any existing module named myModule. Use angular.module('myModule') to retrieve an existing module.
Hope this helps!
I'm rendering template using ngRoute - $routeProvider and I'm trying to render respective controller along with the template. $routeProvider is pointing to that controller and so it gives me an error controller is undefined because I think the App is trying to call the controller before it receives the template.
The templateCtr definition is in the separate JS file.
app.js
...
$routeProvider
.when('/template', {
templateUrl: '/template.html',
controller: 'templateCtr'
})
;
template.html
...
<script src="templateCtr.js"></script>
templateCtr.js
var myApp = angular.module('myApp'); //Getting module reference
myApp.controller('templateCtr', ['$scope', function($scope){
...
}]);
I also came across resolve property using which can load data to be used in controller before view is generated but for that too controller has to present in the memory.
Someone please point me to the correct direction. Thanks!
I followed a tutorial on how to organize and Angular project. I have a ng directory that contains all my controllers, services and my routes.js. This is then bundled all together into an app.js by my gulp config.
My module.js is like this:
var app = angular.module('app', [
'ngRoute',
'ui.bootstrap'
]);
Here's a bit of my routes.js:
angular.module('app')
.config(function ($routeProvider) {
.when('/login', { controller: 'LoginCtrl', templateUrl: 'login.html'})
});
Here's what my working LoginCtrl looks like:
angular.module('app')
.controller('LoginCtrl', function($scope, UserSvc) {
$scope.login = function(username, password) {
...
}
})
The tutorial didn't make use of any Angular modules and I wanted to try one out. I added ui.bootstrap to my page from a CDN and try to change the LoginCtrl to:
angular.module('app')
.controller('LoginCtrl', function($scope, $uibModal, UserSvc) {
...
})
But this throws me the following error:
"Error: [$injector:unpr] Unknown provider: $templateRequestProvider <- $templateRequest <- $uibModal
What is causing this error? In every tutorial I find this seems to be how they load a module, the only difference I see is that the tutorial don't seem to be using a router.
PS: Note that if I use an empty module list [] I get the exact same error. If I use a non-existing module ['helloworld'] I get an errorModule 'helloworld' is not available'. So I'm concluding that my `ui.bootstrap' module is indeed available.
EDIT: Plunker fiddle here: http://plnkr.co/edit/FWHQ5ZDAByOWsL9YeMUH?p=preview
angular route is another module you should not only include but also use like this
in the app module creation
means DI of route
angular.module('app', ['ngRoute']);
Please go through the angular route doc
Remove ['ui.bootstrap'] form controller. You should add dependencies only one time but you add it twice so the second dependency list override the first one.
angular.module('app')
.controller('LoginCtrl', function($scope, UserSvc) {
... })
your routes snippet looks wrong, you should be hanging the when call off $routeProvider and maybe declare $routeProvider as an injected val if it's not being picked up e.g.
angular.module('app')
.config(["$routeProvider", function ($routeProvider) {
$routeProvider.when('/login', { controller: 'LoginCtrl', templateUrl: 'login.html'})
}]);
I have checked your link. I think there is a serious issue with angular and ui bootstrap version.In ui-boostrap dashboard, it is written that 0.12.0 is the last version that supports AngularJS 1.2.x. I have tried with all combinations but it doesn't work with your angular version.
I suggest you to change angular version to latest and ui-bootstrap version to latest so it will work.
Please check out this working Plukr
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.min.js'></script>
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.18/angular-route.js'></script> //change this to latest also.
<script src='https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.0.3/ui-bootstrap.min.js'></script>
<script src='./app.js'></script>
If you want to go with your angular version only. I'd request you to do some R&D. Try with different versions of ui-bootstrap. still if it doesn't work you can make PR.
I have a simple Angular app, calling a controller, which in turn calls a service. This service then loops through an array and returns a few strings.
If I leave the dependencies on the angular.module empty in the controller and the service it does not return the array:
app.js
angular.module('list_app', ['ngRoute'])
.config(function($routeProvider) {
$routeProvider
.when('/list', {
templateUrl: 'views/template.html',
controller: 'ListCtrl'
})
.otherwise({redirectTo: '/list_page'});
});
Controller
angular.module('list_app', [])
.controller('ListCtrl', ['$scope', 'Service', function ($scope, Service) {
Service.getList($scope);
}]);
Service
angular.module('list_app', [])
.factory(
'Service', function Service() {
function getList($scope){
var listRules = $scope.rules=['Test One', 'Test Two'];
var arrayLength = listRules.length;
for (var i = 0; i < arrayLength; i++) {
return(listRules[i]);
}
};
return {
getList: getList
}
});
But if I remove the dependancy [] from the controller and service, it works fine...
Like this:
angular.module('list_app', )...
Can anyone tell me why this is?
Thats because you only need to initialize your module once.
This happens when you use the curly braces:
angular.module('list_app', ['ngRoute'])
Afterwards you dont need them anymore as the module already is initialized.
So afterwards you can just call in all subsequent calls (controller, service):
angular.module('list_app')
Missing Include?
In order to use ngRoute you need to include angular-route before you load your controller. That would be the following (as of right now):
<script type="text/javascript" src="//code.angularjs.org/1.2.14/angular-route.min.js" />
You can also download the minified or full version of this library from the angular site.
Multiple Module Definitions
Another thing I noticed about the code is it looks like you are calling "angular.module" multiple times. You should only do this once, something like:
var list_app = angular.module('list_app', ['ngRoute']);
// define the service as an example:
list_app.factory('MyService', function Routine() {
});
// then define the controller
list_app.controller('MainController, ['$scope', function ($scope) {
}]);
The point is after you define the module once - you should use that reference to make any further declarations! This also might help fix your issue.
Side Note
One more comment is that when you try to inject a dependency that angular can't find the most common error you will see in the console is:
Uncaught Error: [$injector:modulerr] (etc.)
Whenever you see a message like this you should start to look at whether or not you are missing script includes and checking to make sure these are in the correct order.