AngularJS nested routing - angularjs

I'm working a fairly simple AngularJS project with some deep route nesting to select from a nested data structure:
angular.module('doccat', []).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', { templateUrl: 'partials/detail.html', controller: DocDetailCtrl }).
when('/:p0', { templateUrl: 'partials/detail.html', controller: DocDetailCtrl }).
when('/:p0/:p1', { templateUrl: 'partials/detail.html', controller: DocDetailCtrl }).
when('/:p0/:p1/:p2', { templateUrl: 'partials/detail.html', controller: DocDetailCtrl }).
when('/:p0/:p1/:p2/:p3', { templateUrl: 'partials/detail.html', controller: DocDetailCtrl }).
when('/:p0/:p1/:p2/:p3/:p4', { templateUrl: 'partials/detail.html', controller: DocDetailCtrl }).
otherwise({ redirectTo: '/' });
}]);
function DocDetailCtrl($scope, $routeParams) {
var path = [];
if ($routeParams.p0) path.push($routeParams.p0);
if ($routeParams.p1) path.push($routeParams.p1);
if ($routeParams.p2) path.push($routeParams.p2);
if ($routeParams.p3) path.push($routeParams.p3);
if ($routeParams.p4) path.push($routeParams.p4);
// do stuff with path
}
This has up to 5 layers in the path, which should be plenty for my purposes, so it is good enough for now. However, the underlying data could be nested arbitrarily deep, which would require arbitrary routing.
I think the ideal for this would be a route that says 'all the rest of the path goes to any array of parameters', but it doesn't look like there is a way to do anything like that in AngularJS. Just for the sake of completeness, does anyone know of a way to do this?

Check $routeProvider in the doc
angularjs $routeProvider.
Especially, in the definition of 'when', you can read: "path can contain named groups starting with a star (*name). All characters are eagerly stored in $routeParams under the given name when the route matches." So you just need to make sure the route matches and you'll get plenty parameters stored in $routeParams.
I hope it helps.

Related

Is it possible to start angular route with a parameter

I have two URLs in my config file like:
module.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/:param1', {
templateUrl: 'shop.html',
controller: 'RouteController'
}).
when('/contact', {
templateUrl: 'contact.html',
controller: 'RouteController'
}).
otherwise({
redirectTo: '/'
});
}
]);
I am using 'param1' variable to fetch data from server. But when I route to '/contact' it considers 'contact' as a variable too and route it to the upper route i.e. variable route. How can I avoid this without using any extra identifier in route1.

Controllers and how they should be implemented in Angular?

Sorry if this seems like a stupid or simple question but I am a little confused, I have been looking up many different kinds of tutorials for Angular to understand the concept and how to create an application.
The issue is how to you attach a Controller to the Page, I have seen two methods:
Add the controller script to the page
Display Controller inside the app.js where the Website Routing is.
Here is what I have at the moment please let me know if there is any issues in this code:
var app = angular.module('myApp', [
'ngRoute'
]);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/home.html',
controller: 'homeController'
}).
when('/login', {
templateUrl: 'partials/login.html',
controller: ''
}).
when('/signup', {
templateUrl: 'partials/signup.html',
controller: ''
}).
when('/dashboard', {
templateUrl: 'partials/dashboard.html',
controller: ''
}).
otherwise({
redirectTo: '/404',
templateUrl: 'partials/404.html'
});
}]);
app.controller('homeController', ['$scope', function($scope) {
$scope.message = "This is the Home Page";
}]);
Again I am really new to Angular.
Updated to single Controller file:
app.js:
var app = angular.module('myApp', [
'ngRoute'
]);
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/home.html',
controller: 'controllers/homeController.js'
}).
when('/login', {
templateUrl: 'partials/login.html',
controller: ''
}).
when('/signup', {
templateUrl: 'partials/signup.html',
controller: ''
}).
when('/dashboard', {
templateUrl: 'partials/dashboard.html',
controller: ''
}).
otherwise({
redirectTo: '/404',
templateUrl: 'partials/404.html'
});
}]);
controller file:
app.controller('homeController', ['$scope', function($scope) {
$scope.message = "This is the Home Page";
}]);
Nope, your code is fine. I generally use two different files app.js for all the routing options and a controller.js file for the different controllers. A single file seems a bit too cluttered to me.
A single file per controller works but I see for most usercases it turns out just a few lines of code per page for me, but you can if you have extensive codes in each controller
I create a Controller for every model in my database: e.g: ProjectController.js, PeopleController.js, etc. And I use app.js just for routing and general controllers like header, footer, etc.
There isn't a strict way to do it, you have to decide it based on your architecture design. But i can give you a tip: Never define your controllers in your .html file because it makes it awful and less readable.
That's a purely organizational choice. As long as the browser has the code of the controller available, it doesn't matter.
But unless you're creating a tiny demo, having all the controllers defined in a single JavaScript file will quickly become unmanageable: the file will be too large, you'll search for the controllers constantly, and everyone in the team will modify the same file, leading to conflicts, etc.
The simple rule is: one JS file per AngularJS component.
If you're concerned about two many JS files having to be loaded by the HTML page in production, then make sure to learn using gulp or grunt, and to generate a single minified JS file from all the small JS files used during development.
EDIT:
the controller attribute of the route is not supposed to be the path of a JS file. It's supposed to be the name of a controller. It should thus stay exactly as it was in the first, working example.
You need to understand how the browser works: if the HTML contains two <script> elements, it works the same way as if it had a single one with the code of the two scripts concatenated. So splitting the code in two files doesn't change the way the code is written.
Change your route specification to the following code:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/home.html',
controller: 'homeController' //change here
//controller should be the name of the controller,
//not the file containing the controller function
}).
when('/login', {
templateUrl: 'partials/login.html',
controller: ''
}).
when('/signup', {
templateUrl: 'partials/signup.html',
controller: ''
}).
when('/dashboard', {
templateUrl: 'partials/dashboard.html',
controller: ''
}).
otherwise({
redirectTo: '/404',
templateUrl: 'partials/404.html'
});
}]);

What is the difference between these 2 ways to config the $routeProvider? [duplicate]

This question already has answers here:
Angularjs minify best practice
(7 answers)
Closed 7 years ago.
I'm learning Angular and I've seen some examples where the $routeProvider is configured like this:
app.config(function ($routeProvider) {
$routeProvider.
when("/drivers", { templateUrl: "partials/drivers.html", controller: "driversController" }).
when("/drivers/:id", { templateUrl: "partials/driver.html", controller: "driverController" }).
otherwise({ redirectTo: "/drivers" });
});
And in other examples it is configured like this:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when("/drivers", { templateUrl: "partials/drivers.html", controller: "driversController" }).
when("/drivers/:id", { templateUrl: "partials/driver.html", controller: "driverController" }).
otherwise({ redirectTo: "/drivers" });
}]);
Both of them seem to work the same way, but I would like to know what is the difference between calling the config by sending an Array with the '$routeProvider' as a string first and then the function and calling by just using function directly as in the first example.
Thanks.
This is not specific to $routeProvider, it's every module you can declare dependencies for.
What you are seeing is the two of the three different ways to inject your dependencies (Inline Array and Implicit, the other is $inject property), the array injection is better because minification causes problems when it is not in array syntax:
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when("/drivers", { templateUrl: "partials/drivers.html", controller: "driversController" }).
when("/drivers/:id", { templateUrl: "partials/driver.html", controller: "driverController" }).
otherwise({ redirectTo: "/drivers" });
}]);
Wrapping the service names (to be injected) between square brackets and then the function itself, would make it minification safe. This is the inline annotation way of doing it.

AngularJS: $routeProvider with multiple variables in URL

So I'm playing around with learning angular and trying to make a project issue tracker, only I'm having problems with ngRoute and routing.
What I'd ideally like is a system whereby (say) issuetrack.com/projectX returns a view of all the issues for projectX, and issuetrack.com/projectX/XYZ returns a view of the specific issue with the related ID (XYZ).
I've setup my config as such:
tracker.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'static/partials/index_partial.html',
}).
when('/dashboard', {
templateUrl: 'static/partials/dashboard.html',
controller: 'DashboardController'
}).
when('/404', {
templateUrl: 'static/partials/fourOHNOfour.html',
}).
when('/:project', {
templateUrl: 'static/partials/project.html',
controller: 'ProjectController'
}).
when('/:project/:issue', {
templateUrl: 'static/partials/issue.html',
controller: 'IssueController'
}).
otherwise({
redirectTo: '/404'
});
$locationProvider.html5Mode(true);
}]);
But every time I visit (say) localhost:8080/example/1 the page just hangs and becomes unresponsive. localhost:8080/example works completely fine though.
Is what I've done the right way to go about it, or is there another way my googling hasn't been able to find?
Thanks!
Fixed! After several hours...
All you need is:
<base href="/" />
In the head of the index page where the ng-view is.

It it possible to use ngroute to pull different html pages (not partials)?

Hopefully I can explain this properly. On the Angular tutorial, you can use partials doing this:
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
We've all done it and it works great, but for the first time I'm using a different login.html page that doesn't have anything in common with the rest of the pages. Is there a way I can use ngRoute to setup the controller and just load the entire login.html page instead of pointing it at a partial?

Resources