Angular routing params issue with uri - angularjs

what I can do with this:
I have:
appPath/courses - list
appPath/courses/:id - route with param
appPath/courses/add - route to add new course
And when I type appPath/courses/add it going to appPath/courses/:id .when clausule.
How to fix that?
.when("/courses", {
templateUrl: "App/courses/index/view.html",
controller: "CoursesIndexCtrl"
})
.when("/courses/add", {
templateUrl: "App/courses/add/view.html",
controller: "AddCourseCtrl"
})
.when("/courses/:id", {
templateUrl: "App/courses/details/view.html",
controller: "CourseDetailsCtrl"
})

Just change the order:
appPath/courses - list
appPath/courses/add - route to add new course
appPath/courses/:id - route with param

/courses/:id and /courser/add are quite the same for the router. you will ending up overwriting either one or another.
give up on one othe those routes and adopt a longer path, for example:
/courses/add
/courses/detail/:id

Related

passing parameters in nested views with ui-router

I am running into trouble understanding how you can correctly pass parameters using AngularJS.
This is the code I was trying to use in my app.js file for the nested views, however, the nest state never properly renders.
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('news', {
url: '/news',
templateUrl: 'templates/news.html',
controller: 'NewsCtrl'
})
.state('news.id', {
url: '/news/:id',
templateUrl: 'templates/news.id.html',
controller: 'NewsCtrl'
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/news');
})
It will try and change the url to #/news/news/:id versus just #/news/:id.
And if I try and change the path to just be the #/news/:id, then the pages do not render correctly.
What is the best approach to achieve these nested views with parameters?
According to ui-route wiki:
When using url routing together with nested states the default
behavior is for child states to append their url to the urls of each
of its parent states.
If you want to have absolute url matching, then you need to prefix
your url string with a special symbol '^'.
So in your case, you should try
.state('news.id', {
url: '^/news/:id',
templateUrl: 'templates/news.id.html',
controller: 'NewsCtrl'
});

I want to apply the parameters in the ui router dynamically

I have some parameters for category's URL like /:rootcategory/:sub/:sub which is dynamic and for product I have to route like /product/:productname/:producturl..... It is working good using ui-sref but when I come on the URL and refresh it the config got confused and in both URL case it sends me on the category page.
.state('category3',{
url: '/:name1/:name2/:name3',
templateUrl: 'template/product/productsgridpage.html',
controller: 'categoryCtrl',
parent: 'productpagelayout'
})
.state('product', {
url: '/product/:name1/:name2',
templateUrl: 'template/product/detailpage.html',
controller: 'productCtrl',
parent: 'productpagelayout',
})
Updated Answer:
The problem was category also validates product pages, url parameter of category state (/:name1/:name2/:name3) will accept (/product/disc/test) because name1 does not have any special checks to restrict the keyword products from not passing through. So what I suggest is have a regex check which will restrict the keyword product, so that this issue will not occour.
The regex for category will be like
url: '/{name1:\b(?!\bproduct\b)\w+\b}/:name2/:name3',
if name1 parameter starts with product the regex check will fail and category state will not be entered, so it will go to product state, this is what is needed by us.
.state('category3',{
url: '/{name1:\b(?!\bproduct\b)\w+\b}/:name2/:name3',
templateUrl: 'template/product/productsgridpage.html',
controller: 'categoryCtrl',
parent: 'productpagelayout'
})
.state('product', {
url: '/product/:name1/:name2',
templateUrl: 'template/product/detailpage.html',
controller: 'productCtrl',
parent: 'productpagelayout',
})
Previous Answer:
Since you pass "products/hplaptop5050/hp-laptop" it is taking products parameter as a category itself, thus goes to category instead, you need a static variable or even an unique input variable so that it does not get confused, might I suggest something like "/{categoryid:int}/:name1/:name2/:name3" or "/0/:name1/:name2/:name3", so that we have a clear difference from the product and category page.
.state('category3',{
url: '/{categoryid:int}/:name1/:name2/:name3',
templateUrl: 'template/product/productsgridpage.html',
controller: 'categoryCtrl',
parent: 'productpagelayout'
})
.state('product', {
url: '/product/:name1/:name2',
templateUrl: 'template/product/detailpage.html',
controller: 'productCtrl',
parent: 'productpagelayout',
})
Please read the section state declaration page from UI router docs, you can come up with a different approch if needed.
Reference: ui router state docs

Angular ui-router parameter causes conflicts with other states

Just to give some context, I have an Angular application with several separate modules. I am working with ui-router to provide routing to these modules, and I want to use the names of the modules in the URLs. In my Angular app config block I have defined a state for both module1 and module2 with a parameter on each like so:
.state('module1', {
url: '/:module_name',
templateUrl: '/app/modules/module1/views/index.html',
controller: 'someCtrl'
})
.state('module2', {
url: '/:module_name',
templateUrl: '/app/modules/module2/views/index.html',
controller: 'someOtherCtrl'
})
I also have a few links that should take me to the home page of each module.
Naturally, the problem is that the first state will catch all of the rest of my module2 routes, since their URLs all have the same form:
http://localhost:3000/#/module1
http://localhost:3000/#/module2/users
http://localhost:3000/#/module2/books
and so on. I can see how the order that we define the stats is important, but I can't seem to come up with a way to be able to have the module name as a state parameter (this is important since I need it in the corresponding controllers to distinguish from which module an operation is coming from) and avoid this hierarchy problem altogether.
Any ideas?
In your case ui-router will not know which route your are pointing to as they are exactly the same. You would either have to hardcode the module name(assuming there are only a few):
.state('module1', {
url: '/module1',
templateUrl: '/app/modules/module1/views/index.html',
controller: 'someCtrl'
})
.state('module2', {
url: '/module2',
templateUrl: '/app/modules/module2/views/index.html',
controller: 'someOtherCtrl'
})
.state('module2', {
url: '/module2/users',
templateUrl: '/app/modules/module2/views/users.html',
controller: 'someOtherCtrl'
})
.state('module2', {
url: '/module2/books',
templateUrl: '/app/modules/module2/views/books.html',
controller: 'someOtherCtrl'
})
or dynamically inject the html based on the module number
.state('module', {
url: '/module/:moduleId',
templateUrl:
function (stateParams){
return '/app/modules/module' + stateParams.moduleId + '/views/index.html';
}
controller: 'someOtherCtrl'
})
so now to hit module one the path looks like this
http://localhost:3000/#/module/1

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'
});

Angular alias routes in config without redirect

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.

Resources