Angular alias routes in config without redirect - angularjs

I'm probably just missing something simple, but I want to alias my routes. I am trying to get the route /hello_world to just forward to the existing route of /posttemplate. I want to be able to alias my routes like this to give users and easy to remember way to get to dynamic links... Like Permalinks in blogs. Also, this is sort of a separate question, does anyone know of a good way in angular to define all these routes in a json file or xml or something that will keep this clean as I add many routes to it?
application.config(['$routeProvider', '$locationProvider', function AppConfig($routeProvider, $locationProvider, $routeParams) {
$locationProvider.html5Mode(true).hashPrefix('!');
$routeProvider.when("/dashboard", {
controller: 'controllers.DashboardController',
templateUrl: 'templates/dashboard.html'
}).when("/wishlist", {
controller: 'controllers.WishlistController',
templateUrl: 'templates/wishlist.html'
}).when("/login", {
controller: 'controllers.LoginController',
templateUrl: 'templates/login.html'
}).when("/posttemplate", {
controller: 'controllers.PostTemplateController',
templateUrl: 'templates/posttemplate.html'
}).when("/hello_world", {
controller: 'DynamicRouteController',
templateUrl: function(params){ return '/posttemplate?id=1' }
}).otherwise({
controller: 'controllers.HomeController',
templateUrl: 'templates/home.html'
});
}]);

I think you should first plan your URL patterns carefully. It seems not a good idea to have /{{post_name}} and /posttemplate at the same level.
Maybe you could try to add a path prefix to all your individual articles, like /post/:post_name.
Then you can just add this to your router config:
.when("/post/:post_name", {
controller: 'DynamicRouteController',
templateUrl: 'templates/posttemplate.html'
}
Then in DynamicRouteController, read post_name from $routeParams and map it to your post IDs. You may add something like a unique_name field to your posts, in which stores the URL (/post/post_name) you want it to be accessible from.
Or, if you really want, you can also put them the same level. Just make sure that the "catch-all" item is at the end of your router configs.
And, if you want, you can definitely save the router configs into a JSON file. Just iterate over an array of config items and pass them to when().

You can use redirectTo to redirect from an "alias" to some other route.
.when("/hello_world", {
redirectTo: '/posttemplate'
}
See the docs on $routeProvider for more info.

Well... Here is what I ended up doing... If anyone knows a better way... just let me know.
routes["/dashboard"] = {
controller: 'controllers.DashboardController',
templateUrl: 'templates/dashboard.html',
aliases: ['/dash','/dasher'],
meta: {
title: "Dashboard",
description: 'This is my description'
}
};
routes["/bucket"] = {
controller: 'controllers.PostTemplateController',
templateUrl: 'templates/posttemplate.html',
aliases: [],
arguments: {
id: 1
},
meta: {
title: "Dashboard",
description: 'This is my description'
}
};
//Incontroller
if (!postId)
postId = $route.current.arguments.id;

Check out this project ui-router. It provides several features to enhance your route and template management.

Related

Dynamic variable in URL in AngularJS

I have an Angular app which has several dynamic fields, each of these fields are changed updated based on config which comes from a backend database.
In order to control what config is used I need to dynamically switch a single variable - I've decided that the URL is the best way to set/switch the variable as there need to be multiple permutations of the site based on the URL so:-
/:dynamicVariable/
I'm looking for some guidance as to whether this is the best way to do it and what the best way to do it would be? I'm struggling as I don't want to have to set each route for each section like this /:dynamicVariable/homepage /:dynamicVariable/about-us etc etc. Ideally the core module checks it and sets it but the routing ignores it so /:dynamicVariable/ becomes the root.
Hope that makes sense, thanks in advance for your help.
I ended up doing this by using ui.router and nesting states within an abstract parent state which held the client, like so :-
.state('rootClient', {
abstract: true,
url: '/:client',
templateUrl: 'app/layout/layout.html',
controller: 'Layout',
controllerAs: 'layout',
noClient: false,
resolve: {
client: function ($stateParams, ClientService) {
return ClientService.getClient($stateParams.client);
}
}
})
.state('rootClient.home', {
url: '/homepage',
views: {
'content': {
templateUrl: 'app/homepage/homepage.html',
controller: 'Homepage',
controllerAs: 'home'
}
}
});
This way all the routes are under the parent route, I also added a resolve to make sure the client exists before moving to the route. Hopefully this will help someone else down the line.
Cheers

AngularJs UI router - one state with multiple URLs

I have a request to add in another URL parameter that directs to a state that I already have set up. For efficiency purposes, I'm trying to see if I can add multiple URLs to point to the same state, or should I just use the $UrlRouterProvider.when() method to re-direct to that state in this new case.
Ex. this is what already exists
.state('site.link1',
{
url: '/link1',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
and the request is to add www.site.com/newlink that points to the link1 page. Is there something like this;
.state('site.link1',
{
url: '/link1, /newlink',
...
Try using the Regex and a parameter in the url. It is not optimal but works.
.state('site.link1',
{
url: '/{path:link1|newlink}',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
More information on regex in Urls.
To generate links with ui-sref pass the same parameter with the state name as a function
<a ui-sref="site.link1({path:'link1'})" >site link 1</a>
<a ui-sref="site.link1({path:'newlink'})">site new link</a>
You use params:
https://github.com/angular-ui/ui-router/wiki/URL-Routing
.state('site.link',
{
url: '/{link}'
..
}
so when you use the same state like this
$state.go('site.link', {link: 'link1'})
$state.go('site.link', {link: 'link2'})
you can used when() function
.state('site.link1',
{
url: '/link1',
templateUrl: '/views/link1.html',
controller: 'link1Ctrl'
})
then on root config
angular.module('myApp', [...])
.config(function ($urlRouterProvider) {
$urlRouterProvider.when(/newlink/, ['$state','$match', function ($state, $match) {
$state.go('site.link1');
}]);
});
I found this approach to be quite simple and clean: create two equal states, just changing the url property
//Both root and login are the same, but with different url's.
var rootConfig = {
url: '/',
templateUrl:'html/authentication/login.html',
controller: 'authCtrl',
data: {
requireLogin: false
}
}
var loginConfig = Object.create(rootConfig)
loginConfig.url = '/login'
$stateProvider
.state('root', rootConfig)
.state('login', loginConfig)
I had almost the same problem, only with another constraint - I didn't want to use a redirect, since I wanted the url in the browser to stay the same, but display the same state.
This was because I wanted the chrome saved passwords to work for users that already saved the previous url.
In my case I wanted these two urls :
/gilly and
/new/gilly
to both point to the same state.
I solved this by having one state defined for /gilly, and for the second url, I defined an abstract state called /new.
This should be set up like this :
$stateProvider.state('new', {
abstract: true,
url: '/new'
template: '',
controller: function() { }
}).state('gilly', {
url: '/gilly',
template: 'gilly.html',
controller: 'GillyController'
}).state('new.gilly', {
url: '/gilly', // don't add the '/new' prefix here!
template: 'gilly.html',
controller: 'GillyController'
});

Angularjs routeprovider multiple routes lead to same view

So, the workflow with angularjs $routeProvider goes as following,
$routeProvider
.when('/main1', {
templateUrl: 'view1.html',
})
.when('/main2', {
templateUrl: 'view2.html',
})
My question is, is there any way of simplifying the following code. If when('/main1') and when('/main2') point to the same template. So,
$routeProvider
.when('/main1', {
templateUrl: 'view1.html',
})
.when('/main2', {
templateUrl: 'view1.html',
})
The question is asked because if we have multiple languages on the site, and we want to have multiple translations of the url.
Another solution would be to recognize if the site is using .com or .de for instance, and thus adjust to the correct /main1 or /main2 translation. So for instance,
var url = window.location.href;
var main;
if (url.match(/.de/) !== null){
main = "/main1";
}else{
main = "/main2";
}
$routeProvider
.when(main, {
templateUrl: 'view1.html',
})
But semantically, this doesn't seem to be the best solution as I like to keep configuration options set in the run block after the config. We also can't inject factories (only providers, I may be mistaken though) to config.
I would go for putting the language as first url segment in the route.
$routeProvider.when('/:lng/main', {
templateUrl: 'main.html',
controller: function($routeParams){
var lng = $routeParams.lng;
}
})
Though it would be really nice if the $routeProvider would provide this functionality where the an url segment can be isolated. I ain't that pretty putting :lng in each route.

How can I change my AngularJS routes to file?param1=a&param2=b format?

I need to change an existing AngularJS application from using URLs in the format:
example.com/thePage/#/section/1/subsection/1
To making the section & subsection parameters readable by the server with a format like so:
example.com/thePage?section=1&subsection=1
The environment does not offer something like mod_rewrite, so I need to change the routing in Angular to make it handle & generate these URLs. I believe I can do this using $locationProvider.html5Mode(true); however I’m not sure how to proceed from there. I’ve tried updating the existing routing to something like the below, however it fails to return a view (as if the routing isn’t working.
$stateProvider
.state('section', {
abstract: true,
url: '?section',
views: {
'header': {
template: '<h3></h3>'
},
'main': {
templateUrl: constants.baseUrl + 'views/section.html',
controller: 'sectionCtrl',
resolve: {
section: ['sectionervice', '$stateParams',
function (sectionervice, $stateParams) {
return sectionervice.getsection($stateParams);
}],
subsection: ['sectionervice', '$stateParams',
function (sectionervice, $stateParams) {
return sectionervice.getsubsection($stateParams);
}]
}
}
}
})
.state('section.detail.subsection', {
url: '&subsection=:sectionId',
views: {
'main': {
templateUrl: constants.baseUrl + 'views/section.detail.subsection.html',
controller: 'DictionaryCtrl'
}
}
});
It seems that $stateProvider may only work with the forward-slash(/) parameter delimiter. Is there another way to achieve this?
In the ui-router website has a simple example of you trying to do.
Maybe you can do the same thing, see the RouteProvider and StateProvider settings.
url: http://angular-ui.github.io/ui-router/sample/app/app.js
In the server side you can retrieve the url, so you can get your parameters.
[Edit]
About $locationProvider.html5Mode(true); you can do this and do the settings in route and state providers too, that don't interfere in functionality

ui-router: A route with no view template

Is it possible to setup a route in ui-router that only has a controller? The purpose being that at a certain URL, the only thing I'd like to do is take action programatically, and not display anything in terms of a view. I've read through the docs, but I'm not sure if they offer a way to do this.
Yes, I have read this: https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-open-a-dialogmodal-at-a-certain-state, but that is not quite what I am looking for.
For example, let's just say I have a basic body with view:
<body ui-view></body>
And some basic config:
// Routes
$stateProvider
.state('myaction', {
url: "/go/myaction",
onEnter: function() {
console.log('doing something');
}
});
When /go/myaction is visited, the view is blank. Is it possible to do this?
I was able to solve this problem by redirecting the headless state I was taking programmatic action in, to a state WITH a view at the end of the headless state:
$stateProvider
.state('myaction', {
url: "/go/myaction",
onEnter: function() {
console.log('doing something');
}
controller: function($state) {
$state.go('home');
}
});
You can't have a controller without a view but you can use onEnter instead of a controller. If you don't want to change the current view when accessing this state you can define it as a child state:
$stateProvider
// the parent state with a template
.state('home', {
url: '/home',
templateUrl: '/home.html',
controller: 'HomeCtrl'
})
// child of the 'home' state with no view
.state('home.action', {
url: '/action',
onEnter: function() {
alert('Hi');
},
});
Now in home.html you can do something like this:
<a href ui-sref=".action">Greet me!</a>
From the docs:
Warning: The controller will not be instantiated if template is not defined.
Why don't you use an empty string as a template to overcome this?
Yes, you can do that. Use absolute view names to re-use the <ui-view> of another state.
Take a look at this example:
Users go to my app, but depending on them being authenticated or not, I want to send them to a public or private page. I use the index state purely to see if they're logged in or not, and then redirect them to index.private or index.public.
The child states make use of absolute view names to use the <ui-view> element that corresponds to the index state. This way, I don't need to make a second nested <ui-view>.
$stateProvider.state('index', {
url: "/",
controller: 'IndexCtrl'
}).state('index.private', {
views: {
"#": {
templateUrl: 'private.html',
controller: 'PrivateCtrl'
}
}
}).state('index.public', {
views: {
"#": {
templateUrl: 'public.html',
controller: 'PublicCtrl'
}
}
});
A small note on this example: I'm using the # shortcut here. Normally you would use viewname#statename.
My solution for this was just to include a template (html file) that is blank.

Resources