can not config rootScope to setup routing address - angularjs

When loading a routing address into the routeProvider in .config stage, I want to sametime setup the route addresses under $rootScope, so that all the other services can access the routing correctly.
for example, like this:
$rootScope.jsModules='js/modules/';
$rootScope.appModule={
addressbookHomeModule: {
mName:'homeController',
route: 'addressbook-home/',
template: route+'home.html',
controller: route+'homeController.js',
},
However, I found and researched that its not possible to config $rootScope at the point of .config.
If its possible to config $rootScope just by attaching another object onto it, may I ask the way to do that, if possible an example will be a great help.
If no, I wonder if there a better way and more efficient way to store the routing location string like partials/confirmed.html so that all the other services can access the route correctly when I only need to config the string of the routing location once instead of all around the files in all the services?

We can use angular.constant..We can inject constants into pretty much anything (factory service provider etc) once its created.for eg
Angular.module('app).constant('routes',{home:'/'})

Related

Remove an already-registered $state

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.

Angular adding extra logic to 404 handling on non angular routes

I have an angular site hosted in S3, and I have a 404 route set up (I use hash), if someone for example does
mysite/#/gibberish
goes to
mysite/#/404
and on the s3 bucket we have a redirect rule in place for
mysite/gibberish
goes to
mysite/404.html
all is well
Now I just want to add an extra logic on top that if someone types in
mysite/customerid
which is a 404 to somehow redirect this to an angular controller so I can send this request to right page.
So somehow in my redirect in S3 rule add a reg exp for some incoming request and rather than serve 404.html send it i.e. mysite/#/handlethis
Is this possible ?
Depending on the router of your choice, you could do something like the following (which is what we've done (well, not precisely this, but close)):
ui-router
app.config(function ($urlRouterProvider) {
var regx = /\/#\//; // match against /#/
$urlRouterProvider.otherwise(function ($state, $location) {
if (!regx.test($location.path()) { // if no match
$state.go('customHandlingState', /** params **/, /** configuration **/ });
// Transition to your custom handler state, with optional params/config.
}
});
});
You could pair this up with custom stateChange[Start|Stop|Error|Success] handlers in the run block of your app to customise it to your liking.
I would supply an example of how to do this with ngRoute, but I gave up on ngRoute two years ago and haven't looked back since. As such I have no suggestion to give, nor was I able to find a solution to the problem you present.
I would strongly suggest you scrap the S3 portion of this recipe as it will make your life a lot easier when it comes to client side routing (speaking from personal experience here, it's my opinion on the matter - not fact) and handle your 404's/500's on the client with custom state handlers.
If need be you could hook into some logging service and store some data whenever a client/person ends up in an erroneous state.
I suppose my 'counter question' is; What do you gain from using S3 redirect rules? So as to get a better understanding for the needs and goals here.
Some reference material to go along:
ui-router#$state.go
ui-router#$urlRouterProvider.otherwise
I would suggest using routeParams
https://docs.angularjs.org/api/ngRoute/service/$routeParams
the route would look like this:
/mysite/:cid
then access the id with the controller:
$routeParams.cid
I hope this could help
You can manually configure your server to always serve your index.html(your main html file which includes reference to angular script) on all incoming http requests. Client routing will be handled by Angular

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)

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.

Different base url for page routing and templates/partials/RESTful API

My Angular app is splitted into several subapps. I'm working with laravel which is also responsible for the routing between the subapps.
So there are the following urls handled by laravel:
ModuleX: /moduleX
ModuleY: /moduleY
ModuleZ, Item n: /moduleZ/item-n (unlimited amount of items)
And finally on top of these there are my 3 Angular subapps.
So for example: /moduleZ/item-1/#/hello/world
Additionally the templates, partials and a RESTful API are served by laravel under the following urls:
/templates
/partials
/api
If I set the base url with the html tag <base href="http://www.example.com/app/"> I can use relative urls for templates, partials and the api but not for the routing. I'll allways have to add the module url part like that moduleX/#/hello/world.
If I set the base url like for example <base href="http://www.example.com/app/moduleX/"> I can write all links like #/hello/world but the templates, partials and api requests aren't working anymore.
The whole app also sits in a subfolder so I can't just use for example /templates.
So basically my problem or the question now is, what's the best way for handling the different base urls? I don't really like it to prepend the module name to every link.
Look it's might be a particular solution, but may be you should use filters for urls?
For example:
.filter('routeFilter', [function () {
return function (route) {
if (some condition mean this direct html link){
return 'MODULE-X/' + route;
}else{
return route
}
};
}])
I would suggest you let (sub-)apps know their real base not the parent's one, but you make the server responsible for climbing the path hierarchy to find higher level shared resources for missing local ones. This also makes it very easy to prototype new sub-apps, test changes to common pieces independently first, etc.
In a webserver like Apache, this would look like a rewrite rule (conditional on not finding a file) it just substitutes the same file in the parent hierarchy.
In laravel (according to the router docs) it looks like you can add optional 'directories' to your current rules, i.e.:
Route::get('/.../app/templates/{name}', function($name)
...
becomes:
Route::get('/.../app/{module?}/{item?}/templates/{name}', function($name, $module, $item)
...
You could then use $module and $item if you need to test a resource change with specific sub-app/items.
The drawback in making the server responsible for handling inheritance is the independent client fetch/cache of identical resources with different paths. But you can at least choose between large file inefficiency or access latency by using either rewrites or redirects. You can also always hardcode significant paths in production clients later and still benefit from having a hierarchy for testing and graceful handling of occasional errors in client side links.
You can do it in a simpler way if you use combination of service and directive.
You can implement a directive similar to ngHref which when given a link will transform it and append the given link back. It will be injected with a service which will give it the base url or relative url or anything module specific.
This service which is injected in directive will be configured using serviceProvider in app.config block of each sub-app. Since angular injector have only one instance of each service I think you will need more than one injector or one injector per sub-app. Its unclear whether they share injector among them in your app.
You can configure each service according to module to return different base paths. Which will be appended by directive to each link every time.
With this you can use <base href="http://www.example.com/app/"> and that should solve your problem.
I haven't written any code but I can help if you need it.

Resources