Remove an already-registered $state - angularjs

I was surprised to learn that ui-router shares state across modules.
That's ok, but for our development environment I'd like to clear all the application states and start from scratch.
It's not convenient to avoid defining them in the first case just for our test environment, because the state definition is mixed in with all the other application loading, and we'd like to be sure that the application dependencies are describe the same way in all environments.
So can I clear, or remove one-by-one, the already defined states?
.config( function($stateProvider) {
// TODO: get rid of $state definitions from the app, we don't want them here
}

With angular-ui-router starting from Version 1.0.0 (currently in rc1 version) it is now possible to properly remove states.
Inject $stateRegistry (runtime) or $stateRegistryProvider (config) and call the deregister() method.
Here the detailed API, implemented with this commit

This is not possible. ui-router uses ng-router and ng-router does not expose the routes until after the provider is compiled. Meaning you wouldn't be able to remove states/routes until the app is configured. Which I don't think they will accept a PR.
Edit:
In response to the comment made. The routes objects used by the $routerProvider is available and you can remove routes.
https://github.com/angular/angular.js/blob/master/src/ngRoute/route.js#L451
delete $route.routes['/'];
But the states object used by the $stateProvider is not available.
https://github.com/angular-ui/ui-router/blob/a7d25c6/src/state.js
So ui-router would need to be modified to be able to remove states after config. OR ng-router would need to be modified to be able to remove routes during config.

Related

which is best practice using $routeProvider or using $stateProvider in angularjs?

I am building small app using angularjs and nodejs and i would like to know what is best use case for $stateprovider and $routeProvider.
Please help
Angular's own ng-Router takes URLs into consideration while routing, UI-Router takes states in addition to URLs.
States are bound to named, nested and parallel views, allowing you to powerfully manage your application's interface.
While in ng-router, you have to be very careful about URLs when providing links via tag, in UI-Router you have to only keep state in mind. You provide links like . Note that even if you use in UI-Router, just like you would do in ng-router, it will still work.
So, even if you decide to change your URL some day, your state will remain same and you need to change URL only at .config.
While ngRouter can be used to make simple apps, UI-Router makes development much easier for complex apps.
$stateprovider is used when you want the app to have different states like if you want jst a small section of a screen to be loaded at times instead of the entire screen, the go for State provider and the $state.go(url). Special cases when you have a Sliding Drawer sort of an implementation, where you have a right menu with buttons which load different sub screens.
$routeProider are commonly used. Mostly when you want the entire screen to be changed and redirected to a new one.
Note
While using the $state.go(url); for redirecting your screen, the real link of your screen won't change. It will just change the state and not the url of the page
Not to confuse the issue, but there is a new option in AngularJS 1.5: ComponentRouter
This router, along with the uiRouter ($stateProvider) give you more flexibility than the legacy ngRouter ($routeProvider). The ComponentRouter and uiRouter both have a future if you migrate to Angular2.
That said, it depends on your needs. You may not need the composable and nested views offered by ComponentRouter and uiRouter -- but instead only need simple routes.

How does Angular router know where to route URLs to when they are buried in dependencies?

In the Sample Angular App
For example, in one obscure module of the app, there is a route like:
$routeProvider.when('/projectsinfo', {
templateUrl:'projectsinfo/list.tpl.html',
controller:'ProjectsInfoListCtrl',
resolve:{
projects:['Projects', function(Projects){
return Projects.all();
}]
}
});
I have two questions about this:
1) How does Angular locate this path and put it together with its registry of other paths? Is it because the same $routeProvider is used?
2) Is this a bad coding practice - i.e. putting routes in different modules? Are there advantages to doing it?
I would love if someone could enlighten me. I am just starting out with Angular.
Even though a provider (like routeProvider) can be used in multiple modules (and those modules are dependent on each other), the provider is instantiated only once, which makes is a singleton. So in every module you are dealing with the same provider. Since every module has its own config phase, you can configure it again and in this case the registration ends up in the same registry (internally).
So to answer your first question: yes, it is because the same $routeProvider is used.
To answer your second question: I am a little hesitant to say that this is good coding practice because I haven't seen this pattern anywhere else. But there is definitely potential in it, because you can create modules that are about a set of functionality including pages. It makes sense to define routes for that set of functionality inside that module, so all knowledge about it lives inside that module.
The downside is that urls can be overwritten in other modules that are loaded later on, especially by the main app that takes these modules as dependencies.
angular.module('app',['a','b']);
So if in module 'a' you have '/home' defined as route as well as in 'app', the one defined in 'app' will overwrite the one defined in 'a'.

Dynamic routes in AngularJS?

I'm pretty new to AngularJS, so far I have learnt that providers are used to configure the services that will be used later during the execution phase. Particularly, routes are configured during the configuration phase using $routeProvider and then we can access the routes in our controller using the service $route.
I would like to know if once I have set up the routes with $routeProvider, if it's possible to modify the routes, add new ones or delete existing ones using the service $route (during the execution phase). So basically if we can have a kind of dynamic routes, and if so, how can we achieve this.
Thank you!!
nope, the $route service is configured during the config phase via the $routeProvider service, and this phase happens only once when starting the app.
If you want to add dynamic behavior to the url, you ca still manipulate the search parameter thanks to $location.search().
(and then $watch the changes or whatever you want to do)

What is the difference between $state.go(app.location) and $location.path("app/location")?

I have recently started using ionic framework, it has angular js in it. To navigate between screens, I was using $location.path and it's working great. However, in an example I've downloaded, I saw $state.go being used to redirect to some page. I would like to know the difference between the two.
The $location service is on the angular.js framework out of the box and allow you to manage location object (similar to that in pure javascript).
The $state service is a part of ui-router module and allows you to manage routes in an advanced mode, throughout a state machine management of views.
If you use ui-router, you should prefer to use $state service to manage states/routes because state abstracts the concept of route and you could change the physical routes without changing states.
Besides that, more problems you could have if you run in hashbang mode, in particular in your html links. In this case it's preferable to use ui-sref rather than ng-href (or just href).
In my opinion, you should always think in term of states rather than paths. Obviously you can mix the services if you know what you're doing
Thanks #wilver for answering it.
As I dug deeper into angular and learned different ways of structuring my projects, I got to understand these states and paths better. And yes, I've found states much better than paths.
$state.go, which comes with $stateProvider - a provider by ui-router, will work based on state names. Major difference between previously inbuilt(now you need to include ngRoute) router and states is that "States can have nested states but with router it's not possible. And I suddenly realized that whole of Ionic framework is possible because of this concept - I was able to understand this while working on an angular web app based on ngRoute and ionic app based on ui-router.
Ionic works with app as basic state and all other screens defined as its sub states. That's why you see app.screen1, app.screen2 inside $stateProvider in app.js.
So when you have routes, you use $location.path("<routeUrl>") and
when you have states, you use $state.go("<stateName>")
I use ionic and one of the differences that I have observed but not yet figured out why is that $location.path is much slower than $state.go

Access Provider from Service

Is it possible to access a provider that would normally be used in a config from a service? The reason for doing so is I don't have the information I need yet to be able to do it in the module.config.
The provider I would like to access is the $stateProvider which is part of the ui.router module. Lets say I have a module that is dependent on other modules. I would like to be able to have these dependencies register their "desired" routes/states with a service and then use the service determine which ones I actually register. I was hoping that this wouldn't have to be done in the config since I would effectively only be adding new states, not removing or modified those that are already there. So basically, I want my service to get a list of states/routes and have the service register them rather than doing it in the config.
As commented:
You won't be able to inject a provider after the config phase. However you can inject during the config phase and store the it somewhere until you need it.
For example
app.config(function($stateProvider) {
window.stateProvider = $stateProvider;
});
app.service('myService', function() {
var $stateProvider = window.state provider;
// ...
});
Disclaimer(s)
Though I am suggesting this as a possibility, I am certainly not recommending it. It will make your code hard to test, and I doubt it's officially supported so there's no guarantee the provider will work even if you can access it.
That said, if you need to do this and it works then so be it. Just be sure to test vigorously! :)
I've never used the ui.router module, but I believe it has to be setup in the config because the routes have to be setup before the app is initiated. From my understanding, it works basically the same as the $routeProvider, in that you have to setup everything you want to do in the config.
Its not explicitly said anywhere (that I can see), but the docs/examples found here seem to suggest that the $routeProvider can only be accessed from within a module declaration (ie app.module('myMod', [], function($routeProvider){ ... })) or inside of the app.config function.
I'm going to guess that the $stateProvider acts the same way.

Resources