Dynamic nested component views with UI Router - angularjs

I have an Angular application that already uses UI Router. It currently uses nested views as most people do using the dot notation i.e. parent.childState.
However, it is now apparent that some parts of this application need to be reused elsewhere, lets call this Module A This module is tabbed and currently has a state associated with each tab. Currently, like most UI Router applications, the routes are set up during the application configuration phase.
With this new component Id like it to register its own routes, and that those routes are child routes of whatever parent view they are in.
Is this possible?

You can do the following :
Declare a provider in your Module A which will be able to register all the components of your application where you want to insert your module. One of the parameter will be obvisouly the state prefix. This provider will call the $stateProvider internally, either when you call the provider's function, or when you instantiate the service that match to the provider (the $get).
If you choose the $get function you'll need to add an angular.run() to force the instantiation of the service resulting of the $get. Otherwise the $get will be called later and the states won't be mapped resulting in a $stateNotFound. This is usefull if you want to be able to overload some configuration before the $stateProvider is called, if you don't need that, don't use the $stateProvider in the $get function.
So now all you have to do in others module is to have a dependency on the Module A and use the said provider.

Related

"Synchronise" loading of components in a page

I have an Ionic 1.3 mobile application in which I am using Angular 1.5. Each page is comprised of one or more Angular components and each one of these components may in turn contain other components, thus creating a component tree within the page.
The problem I have is that some of these components might require data from the server, which are loaded in the component's $onInit function. Since this data is retrieved asynchronously (and there might be delays) the result is for the components to appear one after the other in the page (depending on when each one manages to initialise) which doesn't make for a very "native" mobile experience. What I would like to do is find a way to know when all components have finished loading so that I can display the page only after it is really ready (all components are fully rendered).
My original idea was to "register" each component with a service when its controller initialises and then notify the service that the component is ready once the data is loaded. The service can then be responsible for showing the page when all components are ready. My problem with doing this is that components seem to initialise sequentially (ie. component1's controller initialises and then $onInit executes, then component2's controller initialises and $onInit executes, etc.) which means that my service can't really know how many components it is waiting for. Not only that, but also a component's children controllers initialise and their $onInit methods execute after the parent component has finished initialising, which means that the component also can't keep track of whether its children have initialised or not.
An alternative would be to hard-code the number of components somewhere in the page and pass it to the service through the page controller so that it knows how many components to wait for without the components needing to register themselves, but ideally I would like something a bit more maintainable (ie. something that doesn't require me to keep track of components and keep this number up to date myself).
Can anyone think of any other way I can keep track of when my page is ready using either Angular or Ionic? Ideally it would be something that can also be ported to Angular2 / Ionic2 since I expect the app to get upgraded at some point, but any suggestion is welcome.
You can try to use resolve in ui.router or ngRoute:
angular.module('app', ['ui.router'])
.config(['$stateProvider', function($stateProvider) {
$stateProvider.state('mainstate', {
url: 'your-url'
,templateUrl: 'yout_template.html'
,controller: 'YourController'
,resolve: {
yourFirstData: ['serviceDeps', function(serviceDeps){
return serviceDeps.getFirstData();
}]
,yourSecondData: ['serviceDeps', 'yourFistData', function(serviceDeps, yourSecondData){
return serviceDeps.getSecondData(yourFirstData);
}
}
}
}]);
The resolve will get the data and resolve promises before loading controller.
This is an ideia.

AngularJS resource dependencies

I am using AngularJS on top of an MVC application. How can I make my AngularJS app depend on a resource having been loaded? In this case I want to ensure my UserData is loaded BEFORE anything else happens. I am using UI Router and I know I can set resolve states on individual routes but I dont want to have to add this to every route. Is there a global way to do this?
Simple solution: you can add a parent state of the entire app and use only one resolve there.
With this approach, the data that resolves will be available for all the children.
You can get all data in "run" block and put it in some kind of service wrapper.

Moving through a Multi Page Application in AngularJS

I'm structuring a Multi Page App in angular. I have a main app with its ngRoute configured so that the resulting url is something like:
http://localhost:8080/project/main#firstTemplate
http://localhost:8080/project/main#secondTemplate
http://localhost:8080/project/main#thirdTemplate
...
Now I must move to another app in the same project so that the Url is something like:
http://localhost:8080/project/secondary#fourthTemplate
I'm able to achieve this by manipulating the string resulting by $location.absUrl() and pass it to $window.location.href but it's horrible.
Is there a better way to do the same thing?
You should do this by the means of your router. There is a default router in angular, though I would suggest you going with https://github.com/angular-ui/ui-router - as I think it is much better than Angular v1.x defaults.
With that router you can define few states (1 state per each URL), define URL for each state, define views to be displayed in that state, actions on entry/leave etc. Then, you can get access to $state object and its go() method to switch between states - as well as easily have it done automatically on elements by specifying .

Any way to inject a provider with a dependency on another provider in AngularJS config

Given the code:
angular
.module('someApp', ['provider1Module, provider2Module'])
.config(function (provider1ModuleProvider, provider2ModuleProvider){
provider1ModuleProvider.getSomethingSpecific()
})
Given also that provider1ModuleProvider.getSomethingSpecific() depends on a method of provider2ModuleProvider's getSomethingGeneric() method, how can I call this method from within the config?
Right now, when I try to run code similar to this, I get an error that essentially tells me the second provider is not instantiated. Can I explicitly instantiate both providers in the config in some way so that one provider's dependency on the other is resolved?
Essentially, what I'm trying to do is get some data in an abstract view state for some views in UI-router so that I can use it in child views. If my pattern above won't work, any other suggestions?

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)

Resources