Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created November 4, 2013 13:27
Show Gist options
  • Select an option

  • Save bennadel/7302417 to your computer and use it in GitHub Desktop.

Select an option

Save bennadel/7302417 to your computer and use it in GitHub Desktop.
Loading AngularJS Components After Your Application Has Been Bootstrapped
<!doctype html>
<html ng-app="Demo">
<head>
<meta charset="utf-8" />
<title>
Loading AngularJS Components After Application Bootstrap
</title>
<style type="text/css">
a[ ng-click ] {
cursor: pointer ;
user-select: none ;
-webkit-user-select: none ;
-moz-user-select: none ;
-ms-user-select: none ;
-o-user-select: none ;
text-decoration: underline ;
}
</style>
</head>
<body ng-controller="AppController">
<h1>
Loading AngularJS Components After Application Bootstrap
</h1>
<p>
<a ng-click="toggleSubview()">Toggle Subviews</a>
</p>
<!--
The "Before" subview doesn't need any additional assets;
however, the "After" subview relies on a number of assets
that will be loaded after the AngularJS application has been
bootstrapped.
-->
<div ng-switch="subview">
<div ng-switch-when="before" ng-include=" 'before.htm' "></div>
<div ng-switch-when="after" ng-include=" 'after.htm' "></div>
</div>
<!-- BEGIN: Templates For ngInclude. -->
<script type="text/ng-template" id="before.htm">
<p>
Before app bootstrap.
</p>
</script>
<script type="text/ng-template" id="after.htm">
<p ng-controller="LazyController" bn-italics>
{{ message }}
</p>
</script>
<!-- END: Templates For ngInclude. -->
<!-- Load jQuery and AngularJS. -->
<script type="text/javascript" src="../../vendor/jquery/jquery-2.0.3.min.js"></script>
<script type="text/javascript" src="../../vendor/angularjs/angular-1.0.7.min.js"></script>
<script type="text/javascript">
// Create an application module for our demo.
var app = angular.module( "Demo", [] );
// -------------------------------------------------- //
// -------------------------------------------------- //
// After the AngularJS has been bootstrapped, you can no longer
// use the normal module methods (ex, app.controller) to add
// components to the dependency-injection container. Instead,
// you have to use the relevant providers. Since those are only
// available during the config() method at initialization time,
// we have to keep a reference to them.
// --
// NOTE: This general idea is based on excellent article by
// Ifeanyi Isitor: http://ify.io/lazy-loading-in-angularjs/
app.config(
function( $controllerProvider, $provide, $compileProvider ) {
// Since the "shorthand" methods for component
// definitions are no longer valid, we can just
// override them to use the providers for post-
// bootstrap loading.
console.log( "Config method executed." );
// Let's keep the older references.
app._controller = app.controller;
app._service = app.service;
app._factory = app.factory;
app._value = app.value;
app._directive = app.directive;
// Provider-based controller.
app.controller = function( name, constructor ) {
$controllerProvider.register( name, constructor );
return( this );
};
// Provider-based service.
app.service = function( name, constructor ) {
$provide.service( name, constructor );
return( this );
};
// Provider-based factory.
app.factory = function( name, factory ) {
$provide.factory( name, factory );
return( this );
};
// Provider-based value.
app.value = function( name, value ) {
$provide.value( name, value );
return( this );
};
// Provider-based directive.
app.directive = function( name, factory ) {
$compileProvider.directive( name, factory );
return( this );
};
// NOTE: You can do the same thing with the "filter"
// and the "$filterProvider"; but, I don't really use
// custom filters.
}
);
// -------------------------------------------------- //
// -------------------------------------------------- //
// I control the root of the application.
app.controller(
"AppController",
function( $scope ) {
// Since this Controller will be instantiated once
// the application is bootstrapped, let's log it to
// the console so we can see the timing.
console.log( "Controller instantiated (after bootstrap)." );
// I determine which view is rendered.
$scope.subview = "before";
// ---
// PUBLIC METHODS.
// ---
// I toggle between the two different subviews.
$scope.toggleSubview = function() {
if ( $scope.subview === "before" ) {
$scope.subview = "after";
} else {
$scope.subview = "before";
}
}
}
);
// -------------------------------------------------- //
// -------------------------------------------------- //
// Once the DOM-Ready event has fired, we know that AngularJS
// will have bootstrapped the application. As such, we want to
// try adding our "lazy bindings" after the DOM-ready event.
$( lazyBindings );
// I define the modules after bootstrapping. Remember, inside
// of this function, the shorthand methods (ex, app.controller)
// NO LONGER POINTER to the core shorthands; instead, they
// point to the method definitions we defined in the config()
// method executed at application bootstrap.
function lazyBindings() {
console.log( "Lazy bindings added to application." );
// Lazy-loaded controller.
app.controller(
"LazyController",
function( $scope, uppercase, util ) {
$scope.message = util.emphasize(
uppercase( "After app bootstrap." )
);
}
);
// Lazy-loaded service.
app.service(
"util",
function( emphasize ) {
this.emphasize = emphasize;
}
);
// Lazy-loaded factory.
app.factory(
"emphasize",
function() {
return(
function( value ) {
return( value.replace( /\.$/, "!!!!" ) );
}
);
}
);
// Lazy-loaded value.
app.value(
"uppercase",
function( value ) {
return( value.toString().toUpperCase() );
}
);
// Lazy-loaded directive.
app.directive(
"bnItalics",
function() {
return(
function( $scope, element ) {
element.css( "font-style", "italic" );
}
);
}
);
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment