-
-
Save Rubentxu/4ef2f19e796b029b43a063bf1b5f7bfe to your computer and use it in GitHub Desktop.
Angular: decorates/intercepts $controller service
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
/** | |
* @license AngularJS | |
* (c) 2010-2012 AngularJS http://angularjs.org | |
* License: MIT | |
*/ | |
/** | |
* Backward compatibility module for AngularJS | |
* @author Vojta Jina <[email protected]> | |
* | |
* Load this module to enable old-style controllers, where controller and scope are mixed together. | |
* | |
* This module decorates Angular's $controller service: | |
* - if given controller does not ask for $scope, it instantiates it in old-way | |
* - if given controller does ask for $scope, instantiation is delegated to default $controller | |
* service. | |
* | |
* This also allows migrating apps step by step. | |
*/ | |
angular.module('ngScopeController', ['ng'], ['$provide', function($provide) { | |
$provide.decorator('$controller', ['$injector', '$delegate', function($injector, $delegate) { | |
var FN_ARGS = /^function\s*[^\(]*\(([^\)]*)\)/m; | |
var FN_ARG_SPLIT = /,/; | |
var FN_ARG = /^\s*(.+?)\s*$/; | |
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; | |
/** | |
* Return a list of arguments to inject | |
* If no $inject property specified it parse the argument names. | |
* @param fn | |
*/ | |
function inferInjectionArgs(fn) { | |
// assert fn is a function | |
if (!angular.isFunction(fn)) { | |
var error = new Error("Controller must be a function, got " + | |
(typeof fn === 'object' ? fn.constructor.name || 'Object' : typeof fn)); | |
throw error; | |
} | |
if (fn.$inject) return fn.$inject; | |
// guess from argument names | |
var args = []; | |
var fnText = fn.toString().replace(STRIP_COMMENTS, ''); | |
var argDecl = fnText.match(FN_ARGS); | |
angular.forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) { | |
arg.replace(FN_ARG, function(all, name) { | |
args.push(name); | |
}); | |
}); | |
return args; | |
} | |
/** | |
* $controller service | |
* | |
* @param {Function} Class Constructor function of the controller. | |
* @param {Object} scope Related scope. | |
* @return {Object} Instance of the controller. | |
*/ | |
return function(Class, scope) { | |
var injectArgs = inferInjectionArgs(Class); | |
// asking for scope - delegate to original service | |
if (injectArgs.indexOf('$scope') !== -1) { | |
return $delegate(Class, scope); | |
} | |
// not asking for scope - BC hack | |
var ClassPrototype = Class.prototype; | |
for(var key in ClassPrototype) { | |
scope[key] = angular.bind(scope, ClassPrototype[key]); | |
} | |
$injector.invoke(Class, scope); | |
return scope; | |
}; | |
}]); | |
}]); |
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
describe('$controller', function() { | |
var $controller; | |
beforeEach(module('ngScopeController')); | |
beforeEach(inject(function($injector) { | |
$controller = $injector.get('$controller'); | |
})); | |
it('should return instance of given controller class', function() { | |
var MyClass = function($scope) {}, | |
ctrl = $controller(MyClass); | |
expect(ctrl).toBeDefined(); | |
expect(ctrl instanceof MyClass).toBe(true); | |
}); | |
it('should inject arguments and given scope', inject(function($http) { | |
var MyClass = function($scope, $http) { | |
this.$scope = $scope; | |
this.$http = $http; | |
}; | |
var scope = {}, | |
ctrl = $controller(MyClass, scope); | |
expect(ctrl.$http).toBe($http); | |
expect(ctrl.$scope).toBe(scope); | |
})); | |
it('should export all methods to scope if scope not injected', function() { | |
var MyClass = function() { | |
this.prop1 = 1; | |
this.method1 = function(value) { | |
this.prop1 = 2; | |
return value; | |
}; | |
}; | |
MyClass.prototype = { | |
prop2: 1, | |
method2: function(value) { | |
this.prop2 = 2; | |
return value | |
} | |
}; | |
var scope = {}, | |
ctrl = $controller(MyClass, scope); | |
expect(ctrl).toBe(scope); | |
expect(scope.prop1).toBe(1); | |
expect(scope.prop2).toBe(1); | |
expect(scope.method1(true)).toBe(true); | |
expect(scope.method2(true)).toBe(true); | |
expect(scope.prop1).toBe(2); | |
expect(scope.prop2).toBe(2); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment