"Synchronise" loading of components in a page - angularjs

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.

Related

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.

Using Backbone.js how i can ensure that all the app is loaded before any user interaction

I have a web page that was developed using Backbonejs and Marionettejs.
I have a lot of views, the problem is when i enter for the first time to the app or i reload the webpage if i interact (make any click) in the page i think the page stops loading and i receive in the console error that can't navigate.
I tried to resolve this issue using requirejs or ensurejs but I had no success.
There is a way to ensure the web page is loaded completely befor the user send an event or prevent the user to make that?
When you say "page loaded" do you mean the DOM or actually downloaded the files?
To me it sound more like a routing issue. Try to double check if all the callback functions of the marionette router are specified and also the route you want to
navigate to is avaiable.
If you mean the DOM, every Marionette View has 2 callbacks about DOM rendering. The first one: onRender is called when the new HTML is ready to go in the DOM, but not appended yet and onDomRefresh is called when the new HTML is actually in the DOM. So, if you need to know when the page is rendered use onRender, when you also have to know if is in the DOM use onDomRefresh.
Like this:
var test = Marionette.ItemView.extend({
onRender: function() { ... },
onDomRefresh: function() { ... }
})
Require is to load files in a asynchronos way. You could definitely improve the architecture of your app.
Please add more details so i can give u a more specific answer.
I have also made a skeleton of a Backbone / Marionette / Require app. Check it out at: https://github.com/LucaMele/skeleton-marionette-require-gulp

Advantage of angular UIRouter over ng-include?

I'm wondering whether to use angular UI router or just use simple ng-include, i'm failing to fully understand why would i pick to include entire library over the built-in ng-include which gives me about the same functionality with less code?
Can someone explain whats wrong with
<div ng-if="somestate" ng-include="someview"></div>
Can someone explain whats wrong with
<div ng-if="somestate" ng-include="someview"></div>
It doesn't handle URLs in any way. You want the URL to change when you go to another state, and you want the state to change when the URL changes. You want to be able to bookmark a page in your app, or send its URL by email, and come back to this page rather than the home page when opening the bookmark or the link.
It also doesn't allow resolving data before switching to a state.Both ui-router and ngRoute allow doing that: the state changes only when the data needed to display this state has been successfully loaded.
That's the main job of ui-router and ngRoute. ui-router has many other goodies, like events when changing state, named views, state inheritance (very useful to handle a view consisting of several tabs, for example), etc.

Loading controllers when navigating through screens

I'm currently using directives in my ionic app, there directives are normally bind to a angular controller. So my problem is, when I navigate through the app, my controllers are not loading (loads for the first time) and hence I cannot setup some initial values.
Following is an example
I navigate to users screen/page
users controller loads (When I check with Chrome dev tools)
I navigate to home screen
I navigate back to users screen
At this point I expect users controller to load again, to setup my initial values, but it's not happening
I'm not sure if this is the default behavior, or am I missing something?
if you are using nested states, parent.child1, parent.child2, parent only loads 1 for the entire hierarchy, changing from child1 to child 2 will not reload the parent controller, thats one of the pros of using ui-router.
also note that with ionic latest version they introduced view caching so, the controller is only instanciated once for each view, to prevent that you need to use
cache-view="false"
in your ion-view
http://ionicframework.com/docs/api/directive/ionNavView/

Angular UI Router - How to preserve views while switching views

I am I new to Angular and UI Router.
Plunk http://plnkr.co/edit/1wfyrGryfGG5RtXozPFY?p=preview
Setup I have three top level application nav buttons Home, Projects, Help. They load different views home.html, projects.html and help.html using the Angular UI Router ui-view directive. This works good.
The Projects.html view has a tab bar with each tab corresponding to a project: D1, D2 D3 etc., I show the corresponding project tab using url router attributes.
Every time I click the Projects button it is reloading the tab bar completely. I loswe the current tab and hopefully if any nested views inside it. Basically the page contents of Project.html, invoking the controller as well.
I read through the wiki documents and couldnt figure out how to implement my required functionality. I am sure I am missing something. Will it always reload the view?
Question: How to avoid reloading the projects view contents so that I can retain the selected tab and all the contents as-is before switching to Home. Because I would have a lot of nested views and models on each project.
I wanted similar functionality too, but ui-router doesn't yet support it. I forked ui-router to support "parallel states" and submitted it to the project for comment. The gist of the conversation is that ui-router will eventually support some form of parallel states but not yet. In the meantime, you can try my fork of 0.2.10 which provides the parallel states that you want.
Read the conversation here: https://github.com/angular-ui/ui-router/issues/894
View the sample parallel tabs plunk here: http://plnkr.co/edit/YhQyPV?p=preview
Here is the fork; build it with grunt: https://github.com/christopherthielen/ui-router
One option would be to implement a service that can be used to maintain the previous state. Services persist over controller changes, thus they can be used to maintain the previous page state and updated when the route changes. something similar to this would work.
app.factory('persitDataService', [function(currentStateData){
var stateService = {
state:{
//your object data set to passed in data
}
//other functions here
};
return stateService
});
then in the controllers just inject the service and assign to a scope value. When the route changes just reset the data in service to new state and inject into new controller
This should work for the previous page state. If you are wanting to save the states of all previous pages then this becomes a larger problem but should be accomplished in much the same way only with a more complicated service setup.
This could also be combined with local and session storage

Resources