-1

I have been working on a "non trivial" angular JS application and I am somewhat disappointed on myself and this framework for not finding truly viable solutions, to the following problems.

  1. AngularJS should have a mechanism that, before run-time, should be able to do HTTP requests in order to get data and set it to providers. This would be extremely useful in getting route permissions, user data, things you need before actually bootstrapping the app.

Right now, I seen articles describing how to load jQuery before angular, manually bootstrapping angular just after some jQuery's ajax calls -> and inject the received data into Angular.

  1. There should be a middle-ware that can be used in order to verify roots. A hook where, before any root is displayed you can do a check, for example to see if the user is authenticated, a token is stored in session storage, etc.

Right now, I've seen attempts with using the ui-router and the $rootScope.$on('$stateChangeStart') event.

This "somewhat" works, but it's not elegant, not out of the box and if you don't fiddle with the settings, it triggers infinite loops.

  1. Also, the ui-router uses resolves, which are great in getting resources before the view compiles. BUT, gues what, you can't get the "$state" from the resolve function. So, yo can't redirect to another view, if the data you requested isn't the on you wanted.

  2. Angular makes it very complicated to load controllers and views for a state, depending on some data - ergo. user roles. It's not really the way to go, but in some cases, it would be useful to decide which controller to load for which route, directly from the router and not using templates in the view.

The reason behind this post, is to see how you guys tackle with these problems.

I hope you prove me wrong and there are much better ways to do the above, and with code examples, I'd be very interested to know about them.

Dany D
  • 1,189
  • 2
  • 18
  • 44
  • For point 1. If you need some data before a page load, you can set a resolve to complete first: http://stackoverflow.com/questions/14741359/angularjs-dependency-injection-in-resolve – SoluableNonagon Nov 06 '14 at 21:15
  • Elite, it would be nice to get a http request before the config app of angular finished... in order to get users locale, api url's, etc.. – Dany D Nov 06 '14 at 21:17
  • This would be better split into separate questions. – Mike Chamberlain Nov 06 '14 at 21:19
  • 1
    Well, angular requests are asynchronous, so tough request there. – SoluableNonagon Nov 06 '14 at 21:22
  • Mike, it's not just me struggling with these stuff.. and basically, almost any non trivial app encounters them - this is why I wanted to keep the grouped and maybe do some knowledge sharing. If you want me guys to put code on how I do it, I'll gladly do it. – Dany D Nov 06 '14 at 21:24
  • I updated my answer... have you tried declaring a app which loads the info, then bootstraps the main application with the given info – SoluableNonagon Nov 06 '14 at 21:45
  • 1
    This should really be broken into multiple questions. – New Dev Nov 06 '14 at 21:56

3 Answers3

1

It sounds like you want something like Angular UI's UI Router.

The main feature it seems like you want out of that is the resolve feature. This lets you set promise-based dependencies on your controllers. Thus making sure you have authentication settings, data, etc. resolved before going to your actual app.

Esteban Felix
  • 1,561
  • 10
  • 21
  • Exactly, but.. imagine you have 50 resolves and you'd have to check all of them for auth... I saw an article which explained how to do nested resolves, which would all depend on a main resolve... and do the code there. – Dany D Nov 06 '14 at 21:53
  • @DanyD Well if you have 50 different dependencies for authentication I think you might need to rethink your approach. Or having a main service that resolves all of your auth dependencies for you. – Esteban Felix Nov 06 '14 at 22:08
0

Would this work?

this is manual bootstrap, make sure not to declare ng-app in HTML or BODY tags, which would automatically bootstrap.

Create two modules. First module initialized automatically, to load data you need, and finally bootstraps your second module, the true application.

var configuarationData = null;
var mainApplication = angular.module('myApp', [dependencies]);

/**
 * This function will start up the application and cause all views to be loaded
 */
mainApplication.config(['$routeProvider', '$locationProvider', '$httpProvider', 
    function($routeProvider, $locationProvider, $httpProvider) {

        // do some stuff here regarding configuration

    }
]).run(['$rootScope', '$templateCache', '$http', ,
    function($rootScope, $templateCache, $http) {
        /* We need this run method to make sure certain global services are loaded prior to other controllers/services */
    console.log('configurationData available?', configurationData);
});

var configApplication = angular.module('theConfigurator',[dependencies]);

configApplication.run(function('$http'){
     $http.get('load some data').then(function(success){
          // bootstrap the main application
          configurationData = success.data;
          angular.bootstrap(document, ['myApp']);
     }, function(reasonForFailure){
         console.log('no config data');
     });
});
SoluableNonagon
  • 11,541
  • 11
  • 53
  • 98
  • Elite, this is actually very interesting... but, instead of loading two angular apps, we could do plain javascript ajax requests to get our data and bootstrap manually the app. I'm not sure I remember correctly, but, in a grunt build, I remember I had some problems with the template chache, after manually bootstrapping angular... so I'll have to do some tests. – Dany D Nov 06 '14 at 21:43
  • Another problem is how to elegantly inject the config data into anglar main app. Right now it's a global variable. – Dany D Nov 06 '14 at 21:44
  • How would this work? You can't inject services (eg. $http) at config time - only providers. – Mike Chamberlain Nov 06 '14 at 22:20
-1

See this question for a possible answer to your first question:

use $http inside custom provider in app config, angular.js

If you really need to make HTTP calls before the config phase has finished, then no, Angular cannot do this, because the config phase is executed synchronously, so your http call would be completed after the config has finished.

Could you instead make these configuration calls on the server side before your app loads and then pass them down in your initial page load?

<script>window.initialData = { ... };</script>

var initialData = angular.fromJson($window.initialData);

Else you are stuck using non-Angular http calls and manual bootstrapping of your app.

Community
  • 1
  • 1
Mike Chamberlain
  • 39,692
  • 27
  • 110
  • 158
  • Sure Mike, but imagine a resp API, CORS and a Angular App, this would not bepossible – Dany D Nov 06 '14 at 21:21
  • Another thing is, other JS frameworks have this pitfall... Sencha Touch also has this problem. Plus, I agree in manually bootstrapping angular.. it's just I remember I had some problems with minification of the templates and some weird error when I did it. – Dany D Nov 06 '14 at 21:22