Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

FeatureRequest: support for ordered initialization of an angular app with asynchronous data #5854

Closed
leifhanack opened this issue Jan 17, 2014 · 42 comments

Comments

@leifhanack
Copy link

Hi there,

again and again I see people asking for a solution to do things after the app is initialized.

E.g. this latest thread or this thread which we created.

We have had the same issue and solved it with a 'init-service'. Here is the sample init service and it's detailed documentation.

It would be awesome if we have a build-in support for this reoccurring request. Or should it be sufficient to use the routeprovider and it's resolve block?

Regards, Leif

@gesellix
Copy link
Contributor

👍

There are several forum threads regarding "angular initialization" issues, are there any plans of the angular core team to add a configurable initialization feature?

@leifhanack
Copy link
Author

There is another thread in the google group: https://groups.google.com/forum/m/#!msg/angular/F5yoJevAHNg/qPeMgI5y420J

@malixsys
Copy link
Contributor

Doesn't ui-router's resolve functionality cover this?

@thardy
Copy link

thardy commented Feb 19, 2014

It does not. Resolve has to be added to EVERY controller where it's needed. Most of the discussion has been about data that is needed by every controller. It's a serious pain and not at all elegant to add the same list of resolve's to every controller. Other frameworks handle this with a global resolve. I'd be happy with a global resolve.

@malixsys
Copy link
Contributor

You can easily inherit the configuration...

Something like:
http://jsbin.com/reh/3/edit

@michaelhunziker
Copy link

Plus 1

@gesellix
Copy link
Contributor

Similarly to the resolve on controller level, PR #3295 makes dependency injection resolve lazily by returning promises from service factories.

@czjvic
Copy link

czjvic commented Apr 2, 2014

+1

2 similar comments
@airandfingers
Copy link

+1

@flockonus
Copy link

👍

@steffanhalv
Copy link

@malixsys Same problem there. You also include promise to every controller, which makes the code ugly. We need a common initializer which has promise to be resolved before any controller is run.

+1

@fibinger
Copy link

+1

1 similar comment
@tony-kerz
Copy link

👍

@Narretz Narretz added this to the Backlog milestone Jun 26, 2014
@fabiosussetto
Copy link

Using ui-router, you can probably achieve this by defining a top level parent state using the 'resolve' option. This way you can implement all your bootstrap logic into your own provider and the children states will wait for your logic to be resolved.

@fibinger
Copy link

fibinger commented Jul 8, 2014

I agree with Fabio. Finally I solved my problem with ui-router by creating
a state hierarchy with one shared, root state. This root state is being
initialized by resolving global dependency (in my case loading some static
data from the server).
The good news is that whenever substate changes, root state always remains
unchanged - that's why this static data is loaded only once, at the very
beginning, and is globally available.

@leifhanack
Copy link
Author

Could you give us a little sample/plunker?

@fabiosussetto
Copy link

Sure:

$stateProvider.state('app', {
                url: "/app",
                templateUrl: "partials/base-app.html",
                controller: 'AppCtrl',
                abstract: true,
                resolve: {
                    'UserLogin': function (UserService) {
                        return UserService.getUser();
                    }
                }
            })
            .state('app.profile', {
                url: "/profile",
                templateUrl: "partials/profile/base.html",
                abstract: true
            })
            .state('app.profile.public', {
                url: "",
                templateUrl: "partials/profile/public.html",
                controller: 'ProfileCtrl'
            })

I'm using ui-router as explained above. Note UserLogin can be injected into your controllers and it contains the data about the currently logged user (if any).

@marcellscarlett
Copy link

+1 - I would also be happy with a global resolve.

@raoulus
Copy link

raoulus commented Aug 6, 2014

+1

@dcfsc
Copy link

dcfsc commented Aug 8, 2014

The ui-router nested state works but is still a little tricky. Explicit init resolve would be ideal. +1

@vuk-nikolic
Copy link

+1

5 similar comments
@mickaeltr
Copy link

+1

@freemancw
Copy link

+1

@cyprusglobe
Copy link

+1

@EnSabanNur
Copy link

+1

@andrey-skl
Copy link

+1

@robianmcd
Copy link

It would be great if you could just return a promise from the run block and your routes wouldn't load until it resolves.

@andrewyap
Copy link

+1

@gittycat
Copy link

+1

Using the resolve of a 'root' state seems the least worst option at this point (see Fabio's sample above).

@cquillen2003
Copy link

+1

@cameronlowry
Copy link

+1

@xyNNN
Copy link

xyNNN commented Oct 28, 2014

The solution from @fabiosussetto won't work for directives, or? It is possible to prevent the rendering for directives till the asynchronous data is loaded from the service in the resolve method from the state?

@malixsys
Copy link
Contributor

@xyNNN you can use $q.when(scope.some_property).then(fn) in your link function in directives to wait for the resolve...

@xyNNN
Copy link

xyNNN commented Oct 28, 2014

@malixsys Doesn't exists another, a bit cleaner solution, to preventing the execution of my angularjs application till my promise resolved my information (also working for directives, ...)? You solution is useable, but so i have to implement it in each of my directives- that is more then DRY! ;)

@malixsys
Copy link
Contributor

@xyNNN well, resolve blocks your controller already... maybe if you have a plunker I can check?

@xyNNN
Copy link

xyNNN commented Oct 28, 2014

@malixsys I think it works also with the directives. The only thing i have to do, is to initialize my service in the resolve directly and not in the controller, because my directive is initialized before the controller is blocked - so you get my on the right path 👍 Thanks!

http://plnkr.co/edit/y5lS88mGjNlHJ0uIHvwE?p=preview

@malixsys
Copy link
Contributor

@xyNNN waddabout this ?

@xyNNN
Copy link

xyNNN commented Oct 28, 2014

@malixsys This should be also possible, thanks. But for my use case i need to render a different template depending on the value from my service.

@malixsys
Copy link
Contributor

@xyNNN Ah!! Like so?

@xyNNN
Copy link

xyNNN commented Oct 29, 2014

@malixsys My indeed is to send a request to my API /me to retrieve all information about the user and his roles. Based on this information (especially the user roles) i wanted to show some directives or functionalities in my application.

I don't want to save anything on the client, excepting the token for the authentication and authorization against my REST API.

Do you could follow and understand my indeed? I think the only thing to do is to initialize my UserService in the resolve with the user information and so should have the user information in my service before the directives and controller are rendered.

@xyNNN
Copy link

xyNNN commented Oct 29, 2014

@malixsys I wanted you and all others to know, that i could solve my problem today in the morning. With this approach my information for the application are fetched before the whole application is executed.

Look at the working example here http://plnkr.co/edit/y5lS88mGjNlHJ0uIHvwE?p=preview

Thanks for the hints and your support!

@Narretz
Copy link
Contributor

Narretz commented Oct 26, 2017

This is trivial with ui.router, which should probably be used by most bigger projects.
With ngRoute you can define a general resolve that all your routes use. While not as comfortable, it does the job as well.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests