Created
September 4, 2013 13:42
-
-
Save bennadel/6437102 to your computer and use it in GitHub Desktop.
Using Base Controllers In AngularJS - An Experiment
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html ng-app="Demo"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <title> | |
| Using Base Controllers In AngularJS | |
| </title> | |
| </head> | |
| <body ng-controller="demo.SubController"> | |
| <h1> | |
| {{ title }} | |
| </h1> | |
| <p> | |
| Foo: {{ foo }}. | |
| </p> | |
| <p> | |
| Bar: {{ bar }}. | |
| </p> | |
| <!-- Load jQuery and AngularJS from the CDN. --> | |
| <script | |
| type="text/javascript" | |
| src="//code.jquery.com/jquery-2.0.3.min.js"> | |
| </script> | |
| <script | |
| type="text/javascript" | |
| src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"> | |
| </script> | |
| <script type="text/javascript"> | |
| // Create an application module for our demo. | |
| var app = angular.module( "Demo", [] ); | |
| // -------------------------------------------------- // | |
| // -------------------------------------------------- // | |
| // Set up the Controller-Factory. This is not a feature that | |
| // AngularJS provides out of the box. As such, we have to | |
| // jerry-rig our own factory using the core factory. | |
| (function( core, coreFactory ) { | |
| // Controllers will be defined by dot-delimited namespaces | |
| // that end in "Controller" (ex. foo.BarController). | |
| var pattern = /\.[^.]*?Controller$/i; | |
| // As the factories are invoked, each will return the | |
| // constructor for the given Controller; we can cache these | |
| // so we don't have to keep re-wiring the factories. | |
| var constructors = {}; | |
| // I proxy the core factory and route the request to either | |
| // the Controller provider or the underlying factory. | |
| function factory( name, controllerFactory ) { | |
| // If the given injectable name is not one of our | |
| // factories, then just hand it off to the core | |
| // factory registration. | |
| if ( ! pattern.test( name ) ) { | |
| return( | |
| coreFactory.apply( core, arguments ) | |
| ); | |
| } | |
| // Register the Controller Factory method as a | |
| // Controller. Here, we will leverage the fact that | |
| // the *RETURN* value of the constructor is what is | |
| // actually being used as the Controller instance. | |
| core.controller( | |
| name, | |
| function( $scope, $injector ) { | |
| var cacheKey = ( "cache_" + name ); | |
| var Constructor = constructors[ cacheKey ]; | |
| // If the cached constructor hasn't been built | |
| // yet, invoke the factory and cache the | |
| // constructor for later use. | |
| if ( ! Constructor ) { | |
| Constructor | |
| = constructors[ cacheKey ] | |
| = $injector.invoke( controllerFactory ) | |
| ; | |
| } | |
| // By returning something other than _this_, | |
| // we are telling AngularJS to use the following | |
| // object instance as the Controller instead of | |
| // the of the current context (ie, the Factory). | |
| // -- | |
| // NOTE: We have to pass $scope through as an | |
| // injectable otherwise the Dependency-Injection | |
| // framework will not know how to create it. | |
| return( | |
| $injector.instantiate( | |
| Constructor, | |
| { | |
| "$scope": $scope | |
| } | |
| ) | |
| ); | |
| } | |
| ); | |
| // Return the core to continue method chaining. | |
| return( core ); | |
| }; | |
| // Overwrite the Angular-provided factory. | |
| core.factory = factory; | |
| })( app, app.factory ); | |
| // -------------------------------------------------- // | |
| // -------------------------------------------------- // | |
| // Define the base-controller; since this is not a name-spaced | |
| // controller, it will be routed to the underlying, core | |
| // factory method. | |
| app.factory( | |
| "BaseController", | |
| function() { | |
| function BaseController( $scope ) { | |
| return( this ); | |
| } | |
| BaseController.prototype = { | |
| getFoo: function() { | |
| return( "Foo ( from BaseController )" ); | |
| } | |
| }; | |
| return( BaseController ); | |
| } | |
| ); | |
| // -------------------------------------------------- // | |
| // -------------------------------------------------- // | |
| // Define the "sub-class" controller; since this is a name- | |
| // spaced controller, it will be routed to the wrapper factory | |
| // that will proxy the controller instantiation. | |
| app.factory( | |
| "demo.SubController", | |
| function( BaseController, $document ) { | |
| function SubController( $scope, $document ) { | |
| BaseController.call( this, $scope ); | |
| // Store foo/bar for use in the View-model. | |
| $scope.foo = this.getFoo(); | |
| $scope.bar = this.getBar(); | |
| // Add some other injectables, just to make sure | |
| // the factory wrapper didn't screw up the | |
| // dependency-injection framework. | |
| $scope.title = $document[ 0 ].title; | |
| } | |
| // Extend the base controller. | |
| SubController.prototype = Object.create( BaseController.prototype ); | |
| // Add sub-class methods. | |
| SubController.prototype.getBar = function() { | |
| return( "Bar ( from SubController )" ); | |
| }; | |
| // Override base method; decorate the value provided | |
| // by the super-class. | |
| SubController.prototype.getFoo = function() { | |
| return( | |
| BaseController.prototype.getFoo.call( this ) + | |
| "( overridden by SubClass )" | |
| ); | |
| }; | |
| return( SubController ); | |
| } | |
| ); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment