Angular ui-router parameter causes conflicts with other states - angularjs

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

Related

ui-router - How to load url without $stateParams on refresh?

My oversimplified app.config() has:
$stateProvider.
state("/", {
url: "/",
templateUrl: "main.html"
}).
state("/newCategories", {
url: "/categories/new",
templateUrl: "/views/new_categories.html",
controller: "newCategoriesCtrl"
}).
state("/categoryPages", {
url: "/categories/:address",
templateUrl: "/views/categories.html",
controller: "categoriesCtrl",
resolve: {
categoriesDataResolve: function resolveTemplate($stateParams, DataResolver) {
return DataResolver.resolveTemplates($stateParams.address);
}
}
});
With this I can use ui-serf link with "/newCategories" to load its url: "/categories/new"
<a ui-sref="/newCategories">New Category</a>
However, when I refresh, it thinks that "/new" is part of $stateParams. Therefore it uses a different controller and tries to resolve its template (which is missing, so it gives an error).
For now I fixed it by changing the url from "/categories/new" to "/categories-new" so it won't get confused on refresh. But how do I solve this issue differently? (Maybe ui-router has a some way of dealing with it)
If I understand you right, you want to call different controller a.e. newCategoriesCtrl when user calls /categories/:address where address param is new
Changing /categories/new to "/categories-new is a right way to solve it.
Small tip: its not good practice to use / as prefix for state name. It confuses the developer and can be mixed with original URL.
$stateProvider.
//...
state("newCategories", {
url: "/categories-new",
templateUrl: "/views/new_categories.html",
controller: "newCategoriesCtrl"
}).
state("categoryPages", {
url: "/categories/:address",
templateUrl: "/views/categories.html",
controller: "categoriesCtrl",
resolve: {
//...
}
});

Angular routing params issue with uri

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

Can we use one one controller for two states when changing states using ui-router

I am trying to switch between routes using angular ui-router. I have two views that use exactly same functionality. My view 2 uses almost 90 % functionality from my view one eliminating some of the html code. In that case can I use same controller for two states like this?
// Routes
.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('moduleone', {
url: '/moduleone',
controller: 'moduleoneCtrl',
templateUrl: path + 'views/one.html',
})
.state('module two',{
url: '/moduletwo',
controller: 'moduleoneCtrl',
templateUrl: path + 'views/two.html',
});
}]);
Rather I'd say create a single state which will be to slight tweak displaying template. You can have mapping stored somewhere to decide template name.
CodE
var ids = {"1": "one", "2": two}
.state('module',{
url: '/module/:id',
controller: 'moduleoneCtrl',
templateUrl: function($stateParams){
return path + 'views/'+ ids[$stateParams.id] +'.html';
}
});

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.

AngularJS ui-router with different URL parameters

While using ui-view in AngularJS, I'm trying to use URL parameters inside of nested views.
For entities of a given type, I want to be able to show all of the entities when navigating to the url /entities, but I would also like to see only the entities of a given type if I go to entities/ofcategory/categoryName. Lastly, I also want to be able to navigate to /entities/details/entityName to see the details of one entity.
Is this structure possible?
This is my ui-routercode:
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entities', {
url: '/entities',
templateUrl: 'app/entities/views/entities.html'
})
.state('entities.ofcategory', {
url: '/ofcategory/:categoryName',
templateUrl: 'app/entities/views/entities.ofcategory.html'
}
.state('entities.details', {
url: '/details/:entityName',
templateUrl: 'app/entities/views/entities.details.html'
});
}]);
If I'm navigating to entities/ofcategory/aname or /entities/details/aname I enter the regular entities controller instead of the category or detailsController
One option is to add an abstract state, which serves as a parent to all your entities states. In that case all your urls become relative to this parent state. Please note that you have to define a ui-view in the template of the abstract state, so it could be used for loading the child templates.
app.config(['$stateProvider', function ($stateProvider) {
$stateProvider
.state('entities', {
url: '/entities',
abstract: true,
templateUrl: 'app/entities/views/entities.html'
})
.state('entities.all', {
url: '/',
templateUrl: 'app/entities/views/entities.all.html'
})
.state('entities.ofcategory', {
url: '/:categoryName',
templateUrl: 'app/entities/views/entities.ofcategory.html'
}
.state('entities.details', {
url: '/details/:entityName',
templateUrl: 'app/entities/views/entities.details.html'
});
}]);
app/entities/views/entities.html:
<div>
<h1>Entities<h1>
<div ui-view></div>
</div>

Resources