Giter Club home page Giter Club logo

oclazyload's Introduction

ocLazyLoad

Load modules on demand (lazy load) in AngularJS

Key features

  • Dependencies are automatically loaded
  • Debugger like (no eval code)
  • The ability to mix normal boot and load on demand
  • Load via the service or the directive
  • Use the embedded async loader or use your own (requireJS, ...)
  • Load js (angular or not) / css / templates files
  • Compatible with AngularJS 1.2.x and 1.3.x

Usage

  • Put ocLazyLoad.js into you project

  • Add the module oc.lazyLoad to your application (you can install it with bower install oclazyload or npm install oclazyload)

  • Load on demand: With $ocLazyLoad you can load angular modules, but if you want to load controllers / services / filters / ... without defining a new module it's entirely possible, just use the name an existing module (your app name for example). There are multiple ways to use $ocLazyLoad to load your files, just choose the one that fits you the best.

Using requireJS:

If you decide to use ocLazyLoad with requireJS, you must declare the bootstraped module in the configuration of the provider. More info here

More examples / tutorials / articles

You can find two basic examples in the example folder. If you need more, check out those links:

Service

You can include $ocLazyLoad and use the function load which returns a promise. It supports single dependency (object) or multiple dependencies (array of objects).

Load a single module with one file:

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

Load a single module with multiple files:

$ocLazyLoad.load({
	name: 'TestModule',
	files: ['testModule.js', 'testModuleCtrl.js', 'testModuleService.js']
});

Load multiple modules with one or more files:

$ocLazyLoad.load([{
	name: 'TestModule',
	files: ['testModule.js', 'testModuleCtrl.js', 'testModuleService.js']
},{
    name: 'AnotherModule',
    files: ['anotherModule.js']
}]);

You can also load external libs (not angular):

$ocLazyLoad.load([{
	name: 'TestModule',
	files: ['testModule.js', 'bower_components/bootstrap/dist/js/bootstrap.js']
},{
    name: 'AnotherModule',
    files: ['anotherModule.js']
}]);

If you don't load angular files at all, you don't need to define the module name:

$ocLazyLoad.load([{
	files: ['bower_components/bootstrap/dist/js/bootstrap.js']
}]);

In fact, if you don't load an angular module, why bother with an object having a single files property ? You can just pass the urls. Single file:

$ocLazyLoad.load('bower_components/bootstrap/dist/js/bootstrap.js');

You can also load css and template files:

$ocLazyLoad.load([
	'bower_components/bootstrap/dist/js/bootstrap.js',
	'bower_components/bootstrap/dist/css/bootstrap.css',
	'partials/template1.html'
]);

If you want to load templates, the template file should be an html (or htm) file with regular script templates. It looks like this:

<script type="text/ng-template" id="/tpl.html">
  Content of the template.
</script>

You can put more than one template script in your template file, just make sure to use different ids:

<script type="text/ng-template" id="/tpl1.html">
  Content of the first template.
</script>

<script type="text/ng-template" id="/tpl2.html">
  Content of the second template.
</script>

There is two ways to define config options for the load function. You can use a second optional parameter that will define configs for all the modules that you will load, or you can define optional parameters to each module. For example, those are equivalents:

$ocLazyLoad.load([{
	name: 'TestModule',
	files: ['testModule.js', 'bower_components/bootstrap/dist/js/bootstrap.js'],
	cache: false
},{
    name: 'AnotherModule',
    files: ['anotherModule.js']
    cache: false
}]);

And

$ocLazyLoad.load([{
	name: 'TestModule',
	files: ['testModule.js', 'bower_components/bootstrap/dist/js/bootstrap.js']
},{
    name: 'AnotherModule',
    files: ['anotherModule.js']
}],
{cache: false});

If you load a template with the native template loader, you can use any parameter from the $http service (check: https://docs.angularjs.org/api/ng/service/$http#usage).

$ocLazyLoad.load(
	['partials/template1.html', 'partials/template2.html'],
	{cache: false, timeout: 5000}
);

The existing parameters that you can use are cache and reconfig. The parameter cache: false works for all native loaders (all requests are cached by default):

$ocLazyLoad.load({
	name: 'TestModule',
	cache: false,
	files: ['testModule.js', 'bower_components/bootstrap/dist/js/bootstrap.js']
});

By default, if you reload a module, the config block won't be invoked again (because often it will lead to unexpected results). But if you really need to execute the config function again, use the parameter reconfig: true:

$ocLazyLoad.load({
	name: 'TestModule',
	reconfig: true,
	files: ['testModule.js', 'bower_components/bootstrap/dist/js/bootstrap.js']
});

Directive

The directive is very similar to the service. Use the same parameters:

<div oc-lazy-load="{name: 'TestModule', files: ['js/testModule.js', 'partials/lazyLoadTemplate.html']}"></div>

You can use variables to store parameters:

$scope.lazyLoadParams = {
	name: 'TestModule',
	files: [
		'js/testModule.js',
		'partials/lazyLoadTemplate.html'
	]
};
<div oc-lazy-load="lazyLoadParams"></div>

Bonus: use the dependency injection

As a convenience you can also load dependencies by placing a module definition in the dependency injection block of your module. This will only work for lazy loaded modules:

angular.module('MyModule', ['pascalprecht.translate', {
		name: 'TestModule',
		files: ['/components/TestModule/TestModule.js']
	}, {
		files: [
			'/components/bootstrap/css/bootstrap.css',
			'/components/bootstrap/js/bootstrap.js'
		]
	}]
)

Configuration

You can configure the service provider $ocLazyLoadProvider in the config function of your application:

angular.module('app').config(['$ocLazyLoadProvider', function($ocLazyLoadProvider) {
	$ocLazyLoadProvider.config({
		...
	});
}]);

The options are:

  • jsLoader: You can use your own async loader. The one provided with $ocLazyLoad is based on $script.js, but you can use requireJS or any other async loader that works with the following syntax:

     $ocLazyLoadProvider.config({
     	jsLoader: function(singleFile or [Array of files], callback);
     });
  • cssLoader: you can also define your own css async loader. The rules and syntax are the same than for jsLoader.

     $ocLazyLoadProvider.config({
     	cssLoader: function(singleFile or [Array of files], callback);
     });
  • templatesLoader: You can use your template loader. It's similar to the jsLoader but it uses an optional config parameter

     $ocLazyLoadProvider.config({
     	cssLoader: function(singleFile or [Array of files], config, callback);
     });
  • debug: $ocLazyLoad returns a promise that can be rejected if there is an error. If you set debug to true, $ocLazyLoad will also log all errors to the console.

     $ocLazyLoadProvider.config({
     	debug: true
     });
  • events: $ocLazyLoad can broadcast an event when you load a module, a component and a file (js/css/template). It is disabled by default, set events to true to activate it. The events are ocLazyLoad.moduleLoaded, ocLazyLoad.moduleReloaded, ocLazyLoad.componentLoaded, ocLazyLoad.fileLoaded.

     $ocLazyLoadProvider.config({
     	events: true
     });
     $scope.$on('ocLazyLoad.moduleLoaded', function(e, module) {
     	console.log('module loaded', module);
     });
  • loadedModules: if you use angular.bootstrap(...) to launch your application, you need to define the main app module as a loaded module.

     angular.bootstrap(document.body, ['test']);
     $ocLazyLoadProvider.config({
         loadedModules: ['test']
     });
  • modules: predefine the configuration of your modules for a later use

     $ocLazyLoadProvider.config({
         modules: [{
             name: 'TestModule',
             files: ['js/TestModule.js']
         }]
     });
     $ocLazyLoad.load('TestModule'});

With your router

$ocLazyLoad works well with routers and especially ui-router. Since it returns a promise, use the resolve property to make sure that your components are loaded before the view is resolved:

$stateProvider.state('index', {
	url: "/", // root route
	views: {
		"lazyLoadView": {
			controller: 'AppCtrl', // This view will use AppCtrl loaded below in the resolve
			templateUrl: 'partials/main.html'
		}
	},
	resolve: { // Any property in resolve should return a promise and is executed before the view is loaded
		loadMyCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
			// you can lazy load files for an existing module
             return $ocLazyLoad.load({
                name: 'app',
                files: ['js/AppCtrl.js']
             });
		}]
	}
});

If you have nested views, make sure to include the resolve from the parent to load your components in the right order:

$stateProvider.state('parent', {
	url: "/",
	resolve: {
		loadMyService: ['$ocLazyLoad', function($ocLazyLoad) {
             return $ocLazyLoad.load({
                name: 'app',
                files: ['js/ServiceTest.js']
             });
		}]
	}
})
.state('parent.child', {
    resolve: {
        test: ['loadMyService', '$ServiceTest', function(loadMyService, $ServiceTest) {
            // you can use your service
            $ServiceTest.doSomething();
        }]
    }
});

It also works for sibling resolves:

$stateProvider.state('index', {
	url: "/",
	resolve: {
		loadMyService: ['$ocLazyLoad', function($ocLazyLoad) {
             return $ocLazyLoad.load({
                name: 'app',
                files: ['js/ServiceTest.js']
             });
		}],
        test: ['loadMyService', '$serviceTest', function(loadMyService, $serviceTest) {
            // you can use your service
            $serviceTest.doSomething();
        }]
    }
});

Of course, if you want to use the loaded files immediately, you don't need to define two resolves, you can also use the injector (it works anywhere, not just in the router):

$stateProvider.state('index', {
	url: "/",
	resolve: {
		loadMyService: ['$ocLazyLoad', '$injector', function($ocLazyLoad, $injector) {
             return $ocLazyLoad.load({
                name: 'app',
                files: ['js/ServiceTest.js']
             }).then(function() {
                var $serviceTest = $injector.get("$serviceTest");
                $serviceTest.doSomething();
             });
		}]
    }
});

##Contribute If you want to get started and the docs are not enough, see the examples in the 'example' folder !

If you want to contribute, it would be really awesome to add some tests, or more examples :)

oclazyload's People

Contributors

gbirman-iseatz avatar hupfis avatar johnlindquist avatar ocombe avatar taz avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.