I am making a file explorer with angular.js.
so, I will deal with some long url,
eg:
mydomain/folder1/sub1/grand-sub1/.././
I just learn angular and find out that angular has the $routeProvider, but, it seems I should write lots of "when" to make this work (the template will not used if I don't define the "when").
does angular support "*" to make all of the sub dir's paths use the same template?
or, does any other method to handle this? Thx.
Since $routeProvider doesn't currently support wildcards (see here and the 2 links in the answer), you have to hack it up a little...
http://plnkr.co/edit/OuVRSrDUvdVF5yFDHnmM?p=preview
HTML
/
<br/>
/folder1
<br/>
/folder1/sub1
<br/>
/folder1/sub1/grandsub1
<br/>
JavaScript
app.controller('DirCtrl', function ($scope, $route) {
var p = $route.current.params;
$scope.path = '/';
if (p.p1) $scope.path += p.p1;
if (p.p2) $scope.path += '/' + p.p2;
if (p.p3) $scope.path += '/' + p.p3;
if (p.p4) $scope.path += '/' + p.p4;
if (p.p5) $scope.path += '/' + p.p5;
});
app.config(function ($routeProvider) {
$routeProvider
.when('/', {templateUrl: 'home.html', controller: 'HomeCtrl'})
.when('/dir', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.when('/dir/:p1', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.when('/dir/:p1/:p2', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.when('/dir/:p1/:p2/:p3', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.when('/dir/:p1/:p2/:p3/:p4', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.when('/dir/:p1/:p2/:p3/:p4/:p5', {templateUrl: 'dir.html', controller: 'DirCtrl'})
/* add more as necessary */
.otherwise({redirectTo: '/'});
});
Don't repeat yourself!
var dirRoute = {templateUrl: 'dir.html', controller: 'DirCtrl'};
$routeProvider
.when('/', {templateUrl: 'home.html', controller: 'HomeCtrl'})
.when('/dir', dirRoute)
.when('/dir/:p1', dirRoute)
.when('/dir/:p1/:p2', dirRoute)
.when('/dir/:p1/:p2/:p3', dirRoute)
.when('/dir/:p1/:p2/:p3/:p4', dirRoute)
.when('/dir/:p1/:p2/:p3/:p4/:p5', dirRoute)
Starting in AngularJS 1.2 (currently in release candidate phase), you can use wildcards to match more of a path. From the new documentation:
path can contain named groups starting with a colon and ending with a star (:name*). All characters are eagerly stored in $routeParams under the given name when the route matches.
For example, routes like /color/:color/largecode/:largecode*\/edit will match /color/brown/largecode/code/with/slashs/edit and extract:
color: brown
largecode: code/with/slashs.
It's worth nothing that you now have to include the extra angular-route.js file, as the routing layer is no longer included by default to save file size. Furthermore, your module must declare ngRoute as one of its dependencies. Your code would look like this:
var app = angular.module('app', ['ngRoute']);
app.controller('HomeCtrl', function ($scope, $route) {
});
app.controller('DirCtrl', function ($scope, $routeParams) {
$scope.path = '/' + $routeParams.dir;
});
app.config(function ($routeProvider) {
$routeProvider
.when('/', {templateUrl: 'home.html', controller: 'HomeCtrl'})
.when('/dir/:dir*', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.otherwise({redirectTo: '/'});
});
Working example: http://plnkr.co/edit/BSPWYPnHM7GJRgNCAjoi?p=preview
Related
I'm trying to create so-called 'SEO-friendly' URLs in AngularJS.
In my script.js for the routing I have:
app.config(['$routeProvider',
function($routeProvider) {
$routeProvider.html5Mode(true);
when('/blog', {
templateUrl: 'blog.html',
controller: 'BlogController'
}).
when('/page/ideas', {
templateUrl: 'ideas.html',
controller: 'IdeasController'
}).
otherwise({
templateUrl: 'home.html'
});
}]);
app.controller("BlogController", function($scope) {
$scope.title = 'Blog';
});
app.controller("IdeasController", function($scope) {
$scope.title = 'Ideas';
});
To remove the # from the URL, I am enabling the html5 mode with:
$routeProvider.html5Mode(true);
however, this results in the following error:
Failed to instantiate module exampleApp due to:
TypeError: $routeProvider.html5Mode is not a function
Does anyone have a solution for this issue? It means that the content will not display from the views because of it.
Edit: for anyone wondering, the working code is:
app.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider.
when('/blog', {
templateUrl: 'blog.html',
controller: 'BlogController'
}).
when('/page/ideas', {
templateUrl: 'ideas.html',
controller: 'IdeasController'
}).
otherwise({
templateUrl: 'home.html'
});
$locationProvider.html5Mode(true);
}]);
html5mode method is available there on $locationProvider provider.
You should include $locationProvider in your config phase to make that dependency available in config block & then enable html5mode for # free URL.
Code
app.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
//$routerProvider code here
$locationProvider.html5Mode(true);
}]);
Additionally you have to add <base href="/"> tag on the index.html page
I'm using routeProvider to set the controller and a route param when my application is configured. Here's the code that I'm using:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/person/:uuid/report', { controller: 'CandidateCtrl' }).
when('/person/:uuid/confirm', { controller: 'ConfirmCtrl', }).
when('/person/add', { controller: 'AddCtrl' })
}]);
However, the controller is not being set correctly. Additionally, when I set the controller with ng-controller in the page itself, the routeParams object is empty. What am I doing wrong?
Edit:
I've also tried this, which also isn't associating the controller with the page nor setting the route-params.
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/person/:uuid/report', { controller: 'CandidateCtrl', template: 'templates/report.html' }).
when('/person/:uuid/confirm', { controller: 'ConfirmCtrl', template: 'templates/confirm.html' }).
when('/person/add', { controller: 'AddCtrl', template: 'templates/add.html' })
}]);
Here's the controller that I'm testing this out with:
appController.controller('CandidateCtrl', ['$routeParams',
function($routeParams) {
console.log($routeParams);
}]);
Try to add templateUrl
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/person/:uuid/report', {
templateUrl: 'partials/CandidateCtrl.html', //TODO : replace with the good template
controller: 'CandidateCtrl'
}).
when('/person/:uuid/confirm', {
templateUrl: 'partials/ConfirmCtrl.html', //TODO : replace with the good template
controller: 'ConfirmCtrl'
}).
when('/person/add', {
templateUrl: 'partials/AddCtrl.html', //TODO : replace with the good template
controller: 'AddCtrl'
}).
otherwise({
redirectTo: 'Something' //TODO : replace with the good url
});
}]);
I was serving the views by via my web-mvc. I've since changed it to serve a layout and have the partial pages be kept in the resource folder.
When I click on the Home link, the goTo function is executed. However, it redirects me to a blank page like so:
When I click on the browser's back button, it redirects me to the page I wanted to go to (firstPage).
Any suggestions on what I am doing wrong?
HTML:
<footer ng-controller = "footerLink">
Home
About us
Our Team
Blog
Services
Portfolio
Contact
Sitemap
</footer>
JS
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
}).
when('/buttonView', {
templateUrl: 'buttonView/buttonView.html',
controller: 'buttonViewCtrl'
}).
when('/firstPage', {
templateUrl: 'view2/view2.html',
controller: 'footerLink'
}).
when('/home', {
templateUrl: 'view1/view1.html',
controller: 'logo'
});
}])
.controller('footerLink', ['$scope', '$location', function($scope, $location) {
$scope.goTo = function (url) {
$location.path(url);
};
}])
UPDATE
I directly redirected the anchor to the firstPage route instead of calling another function. Here is what I changed to make it work:
<footer ng-controller = "footerLink">
Home
About us
Our Team
Blog
Services
Portfolio
Contact
Sitemap
</footer>
it is because you do not have a redirection rule or a route configuration for '/' you can redirect the user to home if there is no matching route.
angular.module('myApp.view1', ['ngRoute'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
}).
when('/buttonView', {
templateUrl: 'buttonView/buttonView.html',
controller: 'buttonViewCtrl'
}).
when('/firstPage', {
templateUrl: 'view2/view2.html',
controller: 'footerLink'
}).
when('/home', {
templateUrl: 'view1/view1.html',
controller: 'logo'
}).otherwise({redirectTo: '/home'});
}])
.controller('footerLink', ['$scope', '$location', function($scope, $location) {
$scope.goTo = function (url) {
$location.path(url);
}; // this function is not really required
}]);
and instead of creating another function to redirect user you can use the use the href on html as you are not doing any other processing there except redirecting user.
<footer ng-controller = "footerLink">
Home
About us
Our Team
Blog
Services
Portfolio
Contact
Sitemap
</footer>
I have a website that currently has a URL like this
http://www.bruxzir.com/cases-bruxzir-zirconia-dental-crown/
I am evaluating angular and have so far begun the app with angular-seed. But now I have URLs that look like this
http://localhost:8000/index.html#/cases-bruxzir-zirconia-dental-crown/
I have used meteor for a SPA and that had compatible URL structure. So how can I do this with Angular? basically get rid of the index.html# from the URL. Here is my code.
index.html - The link in the header
<li>Cases</li>
app.js
'use strict';
// Declare app level module which depends on filters, and services
angular.module('myApp', [
'ngRoute',
'myApp.filters',
'myApp.services',
'myApp.directives',
'myApp.controllers'
]).
config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {templateUrl: 'partials/home.html', controller: 'home'});
$routeProvider.when('/features-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/features.html', controller: 'features'});
$routeProvider.when('/science-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/science.html', controller: 'science'});
$routeProvider.when('/video-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/videos.html', controller: 'videos'});
$routeProvider.when('/cases-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/cases.html', controller: 'cases'});
$routeProvider.when('/testimonials-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/testimonials.html', controller: 'testimonials'});
$routeProvider.when('/authorized-bruxzir-labs-zirconia-dental-crown/', {templateUrl: 'partials/labs.html', controller: 'labs'});
$routeProvider.otherwise({redirectTo: '/home'});
}]);
Just use HTML5 mode provided by $locationProvider:
angular.module('myApp', [
'ngRoute',
'myApp.filters',
'myApp.services',
'myApp.directives',
'myApp.controllers'
]).
config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true); //adding this line
$routeProvider.when('/', {templateUrl: 'partials/home.html', controller: 'home'});
$routeProvider.when('/features-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/features.html', controller: 'features'});
$routeProvider.when('/science-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/science.html', controller: 'science'});
$routeProvider.when('/video-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/videos.html', controller: 'videos'});
$routeProvider.when('/cases-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/cases.html', controller: 'cases'});
$routeProvider.when('/testimonials-bruxzir-zirconia-dental-crown/', {templateUrl: 'partials/testimonials.html', controller: 'testimonials'});
$routeProvider.when('/authorized-bruxzir-labs-zirconia-dental-crown/', {templateUrl: 'partials/labs.html', controller: 'labs'});
$routeProvider.otherwise({redirectTo: '/home'});
}]);
I have a 'route' in Angular JS as follows
$routeProvider.when('/foos/:fooId', { controller: FooController, templateUrl: 'foo.html'});
and it works great, unless the :fooId component contains either a '/' or '%2F' (encoded form)
How can I make this work, my 'fooId' can contain /s ?
You can't easily do this because if you use a link with %2F in it, the browser will just decode it for you and it'll end up being /. AngularJS currently doesn't allow you to use / in $route params.
You can double encode it, like in this plnkr: http://plnkr.co/edit/e04UMNQWkLRtoVOfD9b9?p=preview
var app = angular.module('app', []);
app.controller('HomeCtrl', function ($scope, $route) {
});
app.controller('DirCtrl', function ($scope, $route) {
var p = $route.current.params;
$scope.path = decodeURIComponent(p.p1);
});
app.config(function ($routeProvider) {
$routeProvider
.when('/', {templateUrl: 'home.html', controller: 'HomeCtrl'})
.when('/dir/:p1', {templateUrl: 'dir.html', controller: 'DirCtrl'})
.otherwise({redirectTo: '/'});
});
And the link would be: click here.
Another option, if you have a set number of / characters in your parameters can be found here: How can I make the angular.js route the long path
Based on the answer of Langdon, I created a filter which encodes everything twice, and another one which decodes:
.filter('escape', function() {
return function(input) {
return encodeURIComponent(encodeURIComponent(input));
};
})
.filter('unescape', function() {
return function(input) {
return decodeURIComponent(input);
};
});
I use this in my product links as follows:
<a href="#/p/{{product.id}}/{{product.name | escape}}">
On the product page, I decode the product name:
<h1>{{product.name | unescape}}</h1>
You need not to encode anything here. Just add * in your path Param as mentioned below and enable html5Mode
app.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/home', {templateUrl: 'home.html', controller: 'HomeCtrl'})
.when('/base/:path*', {templateUrl: 'path.html', controller: 'pathCtrl'})
.otherwise({redirectTo: '/home'});
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
include
$locationProvider.hashPrefix('');
in your config.