Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazy loading angular.strap components #86

Closed
vlad-nica opened this issue Nov 7, 2014 · 6 comments
Closed

Lazy loading angular.strap components #86

vlad-nica opened this issue Nov 7, 2014 · 6 comments

Comments

@vlad-nica
Copy link

Hi,

How can I lazy load components of a module like angular.strap if the module declares its components as dependencies:

angular.module('mgcrea.ngStrap', [
  'mgcrea.ngStrap.modal',
  'mgcrea.ngStrap.aside',
  'mgcrea.ngStrap.alert',
  'mgcrea.ngStrap.button',
  'mgcrea.ngStrap.select',
  'mgcrea.ngStrap.datepicker',
  'mgcrea.ngStrap.timepicker',
  'mgcrea.ngStrap.navbar',
  'mgcrea.ngStrap.tooltip',
  'mgcrea.ngStrap.popover',
  'mgcrea.ngStrap.dropdown',
  'mgcrea.ngStrap.typeahead',
  'mgcrea.ngStrap.scrollspy',
  'mgcrea.ngStrap.affix',
  'mgcrea.ngStrap.tab',
  'mgcrea.ngStrap.collapse'
]);

If I leave the module defined like above, the app fails to instantiate:

Error: [$injector:modulerr] Failed to instantiate module angularPoC due to:
Error: [$injector:modulerr] Failed to instantiate module oc.lazyLoad due to:
Error: [$injector:nomod] Module 'mgcrea.ngStrap.modal' is not available!

If I remove the dependencies, they load but not compile.

I have a feeling that the only solution is to rewrite all the components so that they all link to same module (e.g.: instead of
angular.module('mgcrea.ngStrap.typeahead').provider('$typeahead') the provider should be directly defined in angular.module('mgcrea.ngStrap)) but please tell me I'm wrong... :)
So, is there any possibility to lazy load the entire module or parts of it without having to intervene in angular.strap components' code?

Thanks!

@ocombe
Copy link
Owner

ocombe commented Nov 7, 2014

Hi !
The problem is the following: "mgcrea.ngStrap.typeahead" is not a part of the module "mgcrea.ngStrap", it's an independant module. Angular doesn't support "partial" modules. If the name is different, it's a different module.

So what you will have to do is load each module independently and in the right order ("mgcrea.ngStrap.typeahead" before "mgcrea.ngStrap").

But you'll have to be careful, because they might depend upon each other. For example:
"mgcrea.ngStrap.typeahead" depends upon "mgcrea.ngStrap.tooltip" and "mgcrea.ngStrap.helpers.parseOptions".
"mgcrea.ngStrap.tooltip" depends upon "mgcrea.ngStrap.helpers.dimensions"
and "mgcrea.ngStrap.helpers.dimensions" has no dependency.

You will have to check the source code to find out all the modules that have no dependencies, load them, and then load the ones that depend upon them, and so on...
It's gonna be a hard work I'm afraid :(

I wonder if there could be a better way. Since all modules are defined in the bundle file, loading it should make all modules available at once.
I'll take a look at it this week end if I have the time.

@vlad-nica
Copy link
Author

Let's say the problem is not including all the dependencies in the right order. Suppose we have a bundle that contains mgcrea.ngStrap module and all its dependencies & templates. How can I attach the mgcrea.ngStrap module to my app module after loading it (lazy)? If I don't specify ngStrap module from the beginning as a dependent module for my app level module, none of ngStrap components will run. But on the other hand, if I'll specify ngStrap as a dependency, angular will fail instantiating my app module if I don't include all the components from the first place (before bootstrap - like in my first post).
The only elegant solution that I can think of is to somehow, after a module gets loaded, to be pushed as a dependency for another module.
E.g.: In the first place we have a module with no dependency angular.module('myAppModule', [])
But when a lazy load is done like this:

$ocLazyLoad.load({
    name: 'myAppModule',
    files: ['ngStrapBundle.js']
}); 

all modules that are defined inside the js bundle, will be pushed as dependencies to myAppModule, therefore everything should compile & run and no will be need to mess with anyone's code.
But is this possible (after the bootstrap has been done)?

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Ok, so I tried it with angular strap and the last version from master: it works if you load the module 'mgcrea.ngStrap' (that will load all the other modules) and if you bundle the angular-strap.js and angular-strap.tpl.js together.
I need to add the possibility to load the files in serie to avoid having to bundle the files together (see issue #47).

@ocombe ocombe closed this as completed in 4ae7a3f Nov 9, 2014
@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Ok it should work now ! You can use the new parameter serie: true to make sure that the tpl file is loaded after the js file.

$ocLazyLoad.load({
    name: 'mgcrea.ngStrap',
    serie: true,
    files: [
        'bower_components/angular-strap/dist/angular-strap.js',
        'bower_components/angular-strap/dist/angular-strap.tpl.js'
    ]
});

It's available in 0.4.0 !

@vlad-nica
Copy link
Author

It works! 😗

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Perfect :)

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

No branches or pull requests

2 participants