I am running through a course at the moment on AngularJS and it has just introduced the concept of routing.
My problem is the app.config function is setup in app.js however, the function doesn't seem to ever be called and therefore the routes are not setup.
The common problem is the ngRoute not being declared however, it is. I'm not sure if there is a problem with the versions of Angular that I'm using but these were taken from the online course.
I have a public plnkr for anyone to view and have a look at http://plnkr.co/edit/L2FG4M?p=preview
(function() {
var app = angular.module("githubViewer", ["ngRoute"]);
app.config(function($routeProvider) {
// If we navigate to /main then the page used will be main.html and the controller
// MainController, if however something else is provided then we will
// redirect to /main as well
$routeProvider.when("/main", {
templateUrl: "main.html",
controller: "MainController"
})
.otherwise({
redirectTo: "/main"
});
});
}());
Any help is appreciated, I've exhausted my options now.
Thanks
Marc
In your MainController.js file, you defined a new module with same name as in app.js:
angular.module("githubViewer", []);
What you want to do is retrieve the already defined module. You can acheive that by removing the []:
angular.module("githubViewer");
Look here at the "Creation versus Retrieval" section.
Related
For some reason, I can't seem to route to the add screen. What am I doing wrong? Here's my app.js
var moviesApp = angular.module('moviesApp', ['ngRoute']);
moviesApp.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'partials/home.html',
controller: 'MoviesController'
})
.when('/add', {
templateUrl: 'partials/add.html',
controller: 'MoviesController'
})
.when('/edit', {
templateUrl: 'partials/edit.html',
controller: 'MoviesController'
});
});
Here's the anchor tag:
Add Movie
Which is contained within my home.html template which is a part of index.html.
The app doesn't crash...it just doesn't do anything.
Any thoughts on what I'm doing wrong?
It may be because of the change in the default hash-prefix in angularjs version 1.6. What you have written works in the given context: Proof
You can confirm this is the case by changing:
Add Movie
to:
Add Movie
If it works look at for possible solutions at:
AngularJS: ngRoute Not Working
If you want to make i behave as you expect (version 1.5) you could choose soultion 3 from the link:
3. Go back to old behaviour from 1.5 - set hash prefix manually
app.config(['$locationProvider', function($locationProvider) {
$locationProvider.hashPrefix('');
}]);
set up a route start event to help debug the problem
.run(function ($rootScope) {
$rootScope.$on('$routeChangeStart', function (event, next, current) {
console.log(event);
console.log(current);
console.log(next);
console.log('$routeChangeStart: ' + next.originalPath)
});
});
just add this to the end of your route config
Just as a side note I would use a state provider over a route provider. State providers let you define a hierarchy. It's a little harder to work with but much more flexible.
There are a ton of examples of using the newer angular directives like ng-blur, ng-focus, form validation, etc. They all work great in a single page, or in plinkr, jsfiddle, etc. with the exception of the people who try to define the function on the global namespace, that mistake is WELL documented.
However, I was having a different problem.
I was using an example from Scotch.io. This one works great...until you introduce it into an SPA that is using angular-route :(
After many hours of fighting with the error 'Argument 'mainController' is not a function, got undefined', I found the answer in a comment from Hajder Rabiee.Thanks Hadjer, Love you man!
Hajder left this comment and in it, he says:
If you're using routes (high probability) and your config has a reference to a controller in a module that's not declared as dependency then initialisation might fail too.
E.g assuming you've configured ngRoute for your app, like
angular.module('yourModule',['ngRoute'])
.config(function($routeProvider, $httpProvider) { ... });
Be careful in the block that declares the routes,
.when('/resourcePath', {
templateUrl: 'resource.html',
controller: 'secondModuleController' //lives in secondModule
});
Declare secondModule as a dependency after 'ngRoute' should resolve the issue. I know I had this problem.
Even with this help it took me a minute to get it working, so I thought I would share my sample code here to help the next poor bastard that gets stuck on this.
First, in the place where i declare my routes:
var app = angular.module('sporkApp', ['ngRoute','validationApp']);
app.config(function ($routeProvider) {
$routeProvider
.when('/home',
{
controller: 'HomeController',
templateUrl: 'home/home.template.html'
})
.when('/tags',
{
controller: 'TagsController',
templateUrl: 'tags/tags.template.html'
})
.when('/test',
{
controller: 'mainController',
templateUrl: 'test/test.template.html'
})
.otherwise({ redirectTo: '/home' });
});
Then, you need to add your controller code somewhere, where it will get loaded in your shell page:
// create angular app
var validationApp = angular.module('validationApp', []);
// create angular controller
validationApp.controller('mainController', function($scope) {
// function to submit the form after all validation has occurred
$scope.submitForm = function() {
// check to make sure the form is completely valid
if ($scope.userForm.$valid) {
alert('our form is amazing');
}
};
});
Finally, you need to add the corresponding ng-app and ng-controller to some page element that wraps the controls you want to validate. I put the following inside of a div tag:
<div ng-app="validationApp" ng-controller="mainController">
So I have an AngularJS application in which I am attempting to bootstrap only after all of the data for the application is loaded. I need to be able to make the requests in JSONP format so I am attempting to load the $resource module by using a .run statement.
Here's how it looks:
(function(){
// Define our app
app = angular.module("GRT", ["ngResource", "ngRoute"])
.run(function($resource){
console.log($resource);
})
// Configure our route provider and location provider
.config(function($routeProvider, $httpProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'views/home.html'
})
.when('/customer-site-registration', {
templateUrl: "views/customer-site-registration.html",
controller: "customerSiteRegistration"
})
.otherwise({
redirectTo: '/'
});
// $locationProvider.html5Mode(true);
});
}())
Basically no matter what I do it wont run that run block. Any ideas?
Run blocks do not run until the Angular application is bootstrapped. I needed this to run before the bootstrapping.
In this setup the ng-app attribute was removed from the enclosing DOM element to prevent auto-bootstrapping and I was doing it manually after running some code.
Since I was only using it to get access to resource, I instead grabbed it manually like this:
var $resource = angular.injector(["ngResource"]).get("$resource");
Hope this helps someone else!
I have really basic use case in my app where I use AngularJS (1.0.8) for front end and Grails for back end. In the app layout I have a language switcher which allows the user to change the language. Switching the language, it does new http request to retrieve the page. Grails renders all language related stuff (i.e. labels) properly translated. This only works for Chrome, FF, and so but not for IE. IE renders proper language just for layout which is rendered by the main request.
I located the problem. I have defined $routeProvider where I load major of the app content. It is cached by default, therefore IE doesn't load templateUrl of $routeProvider because it loads them from cache:
myApp.config(function ($routeProvider) {
$routeProvider.
when('/', {controller: 'MyCtrl', templateUrl: '/eshop/myConfig'})
});
What I don't get is why it works in all other browsers.
I found some post how to clear cache but they doesn't work for me. Is there any solution for me? If not, I find $routeProvider completely useless for my use case.
Post I found:
angularjs clear history when view loaded
AngularJS disable partial caching on dev machine
Below should do it. You can manipulate angularjs's template caches by using $templateCache, so $routeProvider will load the template as new every time you access the controller.
myApp.config(function ($routeProvider) {
$routeProvider.
when('/', {controller: 'MyCtrl', templateUrl: '/eshop/myConfig'})
})
.controller('MyCtrl', function ($scope, $templateCache) {
$templateCache.remove('/eshop/myConfig');
// or
$templateCache.removeAll();
});
I was having the same issue with $routeProvider. And yes, the $templateCache does not help in this situation. Instead of keeping finding the real 'cache' source, I added the stamp parameter after the templateUrl.
In my code:
$routeProvider.
when('/', {templateUrl: '../views/home.html?v='+window.buildNumber, controller: 'HomeCtrll'}).
when('/report', {templateUrl: '../views/form.html?v='+window.buildNumber, controller: 'FormCtrll'}).
otherwise({redirectTo: '/'});
Sadly, I used a global variable "buildNumber" to save my life. Because I also use RequireJS for my AngularJS project, so this "buildNumber" will also be added to every dependency JS file by using the code:
require.config({
urlArgs: "v=" + window.buildNumber,
paths: {....}
});
Then every time the JS source or template html has been changed, I will only need to update that "buildNumber" in global scope. This is just a thought for the future updates in production environment. Hope this helps.
So the only solution I found was to completely disable cache for ajax queries. I found the solution here: https://stackoverflow.com/a/19771501/607038
myModule.config(['$httpProvider', function($httpProvider) {
//initialize get if not there
if (!$httpProvider.defaults.headers.get) {
$httpProvider.defaults.headers.get = {};
}
//disable IE ajax request caching
$httpProvider.defaults.headers.get['If-Modified-Since'] = '0';
}]);
I don't like this solution because it disable cashing for the content which is really static. So if you have better solution than share it.
I have a really simple Angular app that I've distilled to the following:
var napp = angular.module('Napp',['ngResource']);
var CompanyCtrl = function($scope, $routeParams, $location, $resource) {
console.log($routeParams);
};
napp.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/company/edit/:id',
{templateUrl: '/partials/edit', controller: 'CompanyCtrl'}
);
}]);
and the HTML:
<div ng-controller="CompanyCtrl"></div>
When I log $routeParams, it comes up blank. When I use .otherwise(), it will load whatever I've specified there. Any idea what I'm missing?
You have a couple of errors:
You've specified the controller in two places, both in the view (<div ng-controller="CompanyCtrl"></div>) and in $routeProvider (.when('/company/edit/:id', {templateUrl: '/partials/edit', controller: 'CompanyCtrl'}). I'd remove the one in the view.
You have to register the controller in the module when specifying it in the $routeProvider (you should really do this anyway, it's better to avoid global controllers). Do napp.controller('CompanyCtrl', function ... instead of var CompanyCtrl = function ....
You need to specify a ng-view when you're using the $route service (not sure if you're doing this or not)
The new code:
var napp = angular.module('Napp', ['ngResource']);
napp.controller('CompanyCtrl', function ($scope, $routeParams, $location, $resource) {
console.log($routeParams);
});
napp.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/company/edit/:id',
{templateUrl: '/partials/edit', controller: 'CompanyCtrl'}
);
}]);
The template (/parials/edit)
<div> ... </div>
And the app (index.html or something)
... <body> <div ng-view></div> </body>
I've created a working plunker example: http://plnkr.co/edit/PQXke2d1IEJfh2BKNE23?p=preview
First of all try this with
$locationProvider.html5Mode(true);
That should fix your starting code. Then adjust your code to support non-pushState browsers.
Hope this helps!
Not sure if this helps, but I just came across this issue myself, and found that I couldn't log the route params until I had something bound to them.
So,
Router:
var myApp = angular.module('myApp', []);
myApp.config(function($routeProvider){
$routeProvider.when('/projects/:id',
{templateUrl: '/views/projects/show.html', controller: 'ProjectCtrl'}
);
});
Controller:
myApp.controller('ProjectCtrl', function($scope, $routeParams){
$scope.id = $routeParams.id;
console.log('test');
});
View:
<h1>{{ id }}</h1>
When I removed the '{{id}}' from the view, nothing was logged and $routeParams was empty, at least at the time of the controller's instantiation. As some of the answers above have pointed to, the route params are passed in asynchronously, so a controller with no bindings to that property won't execute. So, not sure exactly what you've distilled your snippet down from, but hope this helps!
This may happen (not in the OP's case) if you're using ui-router instead of ngRoute.
If that's the case, use $stateParams instead of $routeParams.
https://stackoverflow.com/a/26946824/995229
Of course it will be blank. RouteParams is loaded asynchronously so you need to wait for it to get the params. Put this in your controller:
$scope.$on('$routeChangeSuccess', function() {
console.log($routeParams);
});
It works for me http://plunker.co/edit/ziLG1cZg8D8cYoiDcWRg?p=preview
But you have some errors in your code:
Your don't seem to have a ngView in your code. The $routeProvider uses the ngView to know where it should insert the template's content. So you need it somewhere in your page.
You're specifying your CompanyCtrl in two places. You should specify it either in the $routeProvider, or in you template using ng-controller. I like specifying it in the template, but that's just personal preference.
Although not an error, you're specifying your CompanyCtrl in the global scope, instead of registering it on your Napp module using Napp.controller(name, fn).
Hope this helps!
You can always go on #angularjs irc channel on freenode: there's always active people ready to help
Could it be that your templateUrl points to an invalid template?
When you change the templateUrl to an unexisting file, you will notice that the $routeParams will no longer be populated (because AngularJS detects an error when resolving the template).
I have created a working plnkr with your code for your convenience that you can just copy and paste to get your application working:
http://plnkr.co/edit/Yabp4c9zmDGQsUOa2epZ?p=preview
As soon as you click the link in the example, you will see the router in action.
Hope that helps!