Angular routing with ng-view is not working - angularjs

I don't understand why I can't get this to work.
I'll share the relevant code, let me know if you need to see more stuff.
Index.html
<div class="col-md-3">Liberals</div>
app.js
var app = angular.module('myApp', ['ngRoute']);
app.config(function ($routeProvider) {
$routeProvider.
when("/liberals", {
templateUrl: "partials/liberals.html"
, controller: "LiberalsController"
});
});
app.controller('LiberalsController', function ($scope, $http) {
var url = "workingURL"; /// changed function to a simple string message to test
$scope.message = "Hello Liberals";
});
(partial view) liberals.html
<h1>Hello</h1>
{{message}}
PS: I'm not working on a political hate website for or against liberals!

As of AngularJS 1.6, the default value of the hashPrefix has been changed to !.
There's two ways to get your routing to work with AngularJS 1.6+:
Add the hashprefix (!) to your href's:
Liberals
Change (remove) the hashPrefix value using $locationProvider:
$locationProvider.hashPrefix('');
I've created a working plunkr in which I used the second approach:
https://plnkr.co/edit/oTB6OMNNe8kF5Drl75Wn?p=preview
The commit regarding this breaking change can be found here

Related

Angular 1.6.1 Dynamic loading Html with routeProvider triggerrs no controller this.$onInit

I build a small app with angular an added the routeProvider to change my ContentView. The Switching betwenn my different htmls works and i can use cars and functions in my html.
var app = angular.module("mainApp", ['ngRoute']);
angular.module("mainApp").config(
[ '$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$locationProvider.hashPrefix('');
$routeProvider.when("/", {
templateUrl : './page1.html',
controller : 'con1'
}).when("/stuff", {
templateUrl : './page2.html',
controller : 'con2'
}).when("/404", {
templateUrl : "./errorPage.html"
})
// else 404
.otherwise({
redirectTo : "/404"
});
} ]);
I added the Functions:
this.$onInit = function() {console.log("test"); };
Do Stuff when my controller is in the Init Mode. (Note: I added this pattern in a other project as well but in this newly project it wont load this.$onInit)
I'm Using Angular 1.6.1 as Webjar and .
Any Ideas why it wont work?
Life-cycle hooks were introduced for directive/component controllers.
They will not fire for the controllers used in $routeProvider mappings.
You can take a look at this jsfiddle and see the output in the console.
Sorry for not writing answer sooner. Yes you guys where right that the lifecyle wont call init if the routingProvider calls the Controller.
I solved it by manuelle triggering the init. I done that by adding the controller to the main body (container) with data-ng-controller="myController"
This calls init on pageload. Kind of hacky but it works great.

Why doesn't $location.path fire the $routeProvider function?

I'm trying to build my first AngularJS single page application. I copied part of the code below and modified it some. I have a menu bar which calls the Navigate method that I added to the mainController.
When I click on the menu button the expected alert message appears in Navigate, but the alert message in the $routeProvider function only fires when the application starts and it never fires again. I can't find a good explanation of this, but logic says the $routeProvider function should fire when a new $location.path is set in Navigate. Is that wrong? How is this supposed to wire up? Is my nested single page controller causing the menu command to fail?
Also, are there really supposed to be two semicolons at the end or should one of them come after the app.config section?
var app = angular.module('myApp', ['ngRoute']);
app.config(['$routeProvider', function ($routeProvider)
{
alert("$routeProvider " + $routeProvider.path);
$routeProvider
.when('/', {
templateUrl: 'App/Views/Home.html',
controller: 'homeController'
})
.when('/about', {
templateUrl: 'App/Views/About.html',
controller: 'aboutController'
})
.otherwise({
redirectTo: '/'
});
}])
app.controller('mainController', function ($scope)
{
$scope.Title = "Default Title";
$scope.Message = "Default Message";
$scope.Navigate = function (myPath)
{
alert("Navigate " + myPath);
$location.path(myPath);
};
});;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<ul class="MenuBar">
<li class="MenuButton FloatLeft" ng-click="Navigate('/home');">Home</li>
<li class="MenuButton FloatLeft" ng-click="Navigate('/about');">About</li>
<li class="MenuButton FloatLeft" ng-click="Navigate('/about');">Log In</li>
</ul>
You're trying to run an alert whenever the $routeProvider function runs but it doesn't quite work that way. The $routeProvider function just tells Angular "Whenever the location path changes, refer to this JSON object to know what to do next." Then your code providers some JSON attributes to Angular such as templateUrl and controller. Your alert function will only run once because the $routeProvider is just setup code to configure Angular's routes.
To run code after going to another "page", just add the code to the controller.
Code Example:
app.controller('homeController', function($scope, $http) {
alert("I'm running the homeController() function now");
});
Also, I noticed that you didn't inject $location into your controller. Without this, $location will just be an undefined object. Change your controller definition like this:
app.controller('mainController', function ($scope, $location)
{
$scope.Title = "Default Title";
$scope.Message = "Default Message";
$scope.Navigate = function (myPath)
{
alert("Navigate " + myPath);
$location.path(myPath);
};
});
Remember that any Angular object starting with the $ dollar sign ($timeout, $http, $routeProvider, etc) must be injected into your controller.
You have a few issues with the code you're showing. Not enough details to know for sure but here's what's wrong.
First:
A module's config block will only be executed once, at the start. You're not seeing the alert within your config beyond once because it's only ever called once during the bootstrap of your module.
Second:
You need to inject services that your controller depends on.
app.controller('mainController', function ($scope) { });
Note that you're missing the $location service here.
app.controller('mainController', function ($scope, $location) { });
Third:
We can't see some missing pieces to your code to help you out. You're not showing us how mainController is actually hooked up to anything. How myPath is being sent to the Navigation function on your controller, etc.
I found a nested controller that I wasn't using. When I took that out part of the menu worked. I say part because on some links instead of calling the Navigate function I was setting the window.location. That seems to fire the $routeProvider and the view changes like it should. When I change the Navigate function as shown below it works. I think setting $location.path() in the Navigate function should do the same thing, but it's not working for me.
$scope.Navigate = function (myPath)
{
alert("Navigate " + myPath);
//$location.path(myPath);
window.location = '#' + myPath;
};

Angular JS problems with Ng-Route, Gulp, and Json

I'm pretty new to the world of front end development and I'm working through my first project with AngularJS. I'm also using Yeoman, Gulp, Bower to set up my project, which is also bran new to me... I've kind of crafted a build from the yo generator Gulp Angular and put my own personal touches to it. I'm sure I did more harm than good :p but I'm learning.
Anyways I've been coding all day and am really stumped why my project is having trouble when I use the ng-route. The home display works correctly but when I try to click on a link to a deeper page it just refreshes back to the home. I'm using Json files rather than a server and the Gulp Angular set up has all my files compiled to another folder when launching a server. Is there any chance the issue could lie within the compiler?
I'm starting to go crazy so I think I'm gonna call it quits for the night but if anyone has the time and the generosity to look over my github repo I would be over joyed :)
Thanks
https://github.com/jleibham/BhamDesigns.git
App Module
(function() {
'use strict';
var bhamDesignsApp = angular.module('bhamDesignsApp', ['ngAnimate', 'ngTouch', 'ngSanitize', 'ngMessages', 'ngAria', 'ngRoute', 'mm.foundation', 'appControllers']);
bhamDesignsApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/projects', {
templateUrl: 'partials/projects.html',
controller: 'ProjectsController'
}).
when('/projects/:projectId', {
templateUrl: 'partials/gallery.html',
controller: 'GalleryController'
}).
otherwise({
redirectTo: '/projects'
});
}]);
})();
App Controller
(function() {
'use strict';
var appControllers = angular.module('appControllers', []);
appControllers.controller('ProjectsController', ['$scope', '$http',
function ($scope, $http) {
$http.get('app/json/projects.json').success(function(data){
$scope.projects = data;
});
$scope.orderProp = '-year';
}]);
appControllers.controller('GalleryController', ['$scope', '$routeParams',
function($scope, $routeParams) {
$scope.projectId = $routeParams.projectId;
}]);
})();
You are calling the wrong url and your routes do not recognize the url you do call with your href, so it redirects you. In you are going to call this:
href="#/json/galleries/(what ever the project.id is)
Then your routing should look similar to this:
when('/json/galleries/:projectId', { /// the rest of your code
You are going to want to use $routeParameters with ngRoute. here is a great example

Why use dependency injection in angularjs for controllers?

I came across this tutorial.
http://justinvoelkel.me/laravel-angularjs-part-two-login-and-authentication/
The author used dependency injection to inject the login controller in app.js like this.
app.js:
var app = angular.module('blogApp',[
'ngRoute',
//Login
'LoginCtrl'
]);
app.run(function(){
});
//This will handle all of our routing
app.config(function($routeProvider, $locationProvider){
$routeProvider.when('/',{
templateUrl:'js/templates/login.html',
controller:'LoginController'
});
});
The login controller file looks like this.
LoginController.js:
var login = angular.module('LoginCtrl',[]);
login.controller('LoginController',function($scope){
$scope.loginSubmit = function(){
console.dir($scope.loginData);
}
});
I don't understand why the dependency injection is required here.
Here is my version of app.js and LoginController.js which works perfectly fine.
app.js:
var app = angular.module('ilapp', ['ngRoute']);
app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.when('/login', {
controller: 'LoginController'
});
}]);
LoginController.js:
angular.module('ilapp').controller('LoginController', [function () {
this.loginSubmit = function () {
console.dir(this.loginData);
};
}]);
Is there any advantage to the author's approach? What am I missing?
First of all, both are correct way and it should work but you can choose any one method depends upon your project.
Approach 1
In your question, the first approach is modular way. Means, you can register a LoginController controller in a new module LoginCtrl. Here module name LoginCtrl is confusing. you can change the name as loginModule. This approach is helpful for you to organize the files structure for your big application. Also, look this post Angular - Best practice to structure modules
var login = angular.module('loginModule',[]);
login.controller('LoginController',function($scope){
$scope.loginSubmit = function(){
console.dir($scope.loginData);
}
});
var app = angular.module('blogApp',[
'ngRoute',
'loginModule'
]);
app.run(function(){
});
//This will handle all of our routing
app.config(function($routeProvider, $locationProvider){
$routeProvider.when('/',{
templateUrl:'js/templates/login.html',
controller:'LoginController'
});
});
Approach 2
If your application contains minimal pages and no need to split multiple modules, then you can write all your controllers in app.js itself

Angular $routeParams is blank

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!

Resources