mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-03-30 23:18:53 +08:00
149 lines
5.4 KiB
JavaScript
149 lines
5.4 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* @ngdoc provider
|
|
* @name $controllerProvider
|
|
* @description
|
|
* The {@link ng.$controller $controller service} is used by Angular to create new
|
|
* controllers.
|
|
*
|
|
* This provider allows controller registration via the
|
|
* {@link ng.$controllerProvider#register register} method.
|
|
*/
|
|
function $ControllerProvider() {
|
|
var controllers = {},
|
|
globals = false,
|
|
CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
|
|
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $controllerProvider#register
|
|
* @param {string|Object} name Controller name, or an object map of controllers where the keys are
|
|
* the names and the values are the constructors.
|
|
* @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
|
|
* annotations in the array notation).
|
|
*/
|
|
this.register = function(name, constructor) {
|
|
assertNotHasOwnProperty(name, 'controller');
|
|
if (isObject(name)) {
|
|
extend(controllers, name);
|
|
} else {
|
|
controllers[name] = constructor;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @ngdoc method
|
|
* @name $controllerProvider#allowGlobals
|
|
* @description If called, allows `$controller` to find controller constructors on `window`
|
|
*/
|
|
this.allowGlobals = function() {
|
|
globals = true;
|
|
};
|
|
|
|
|
|
this.$get = ['$injector', '$window', function($injector, $window) {
|
|
|
|
/**
|
|
* @ngdoc service
|
|
* @name $controller
|
|
* @requires $injector
|
|
*
|
|
* @param {Function|string} constructor If called with a function then it's considered to be the
|
|
* controller constructor function. Otherwise it's considered to be a string which is used
|
|
* to retrieve the controller constructor using the following steps:
|
|
*
|
|
* * check if a controller with given name is registered via `$controllerProvider`
|
|
* * check if evaluating the string on the current scope returns a constructor
|
|
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
|
|
* `window` object (not recommended)
|
|
*
|
|
* The string can use the `controller as property` syntax, where the controller instance is published
|
|
* as the specified property on the `scope`; the `scope` must be injected into `locals` param for this
|
|
* to work correctly.
|
|
*
|
|
* @param {Object} locals Injection locals for Controller.
|
|
* @return {Object} Instance of given controller.
|
|
*
|
|
* @description
|
|
* `$controller` service is responsible for instantiating controllers.
|
|
*
|
|
* It's just a simple call to {@link auto.$injector $injector}, but extracted into
|
|
* a service, so that one can override this service with [BC version](https://gist.github.com/1649788).
|
|
*/
|
|
return function(expression, locals, later, ident) {
|
|
// PRIVATE API:
|
|
// param `later` --- indicates that the controller's constructor is invoked at a later time.
|
|
// If true, $controller will allocate the object with the correct
|
|
// prototype chain, but will not invoke the controller until a returned
|
|
// callback is invoked.
|
|
// param `ident` --- An optional label which overrides the label parsed from the controller
|
|
// expression, if any.
|
|
var instance, match, constructor, identifier;
|
|
later = later === true;
|
|
if (ident && isString(ident)) {
|
|
identifier = ident;
|
|
}
|
|
|
|
if (isString(expression)) {
|
|
match = expression.match(CNTRL_REG),
|
|
constructor = match[1],
|
|
identifier = identifier || match[3];
|
|
expression = controllers.hasOwnProperty(constructor)
|
|
? controllers[constructor]
|
|
: getter(locals.$scope, constructor, true) ||
|
|
(globals ? getter($window, constructor, true) : undefined);
|
|
|
|
assertArgFn(expression, constructor, true);
|
|
}
|
|
|
|
if (later) {
|
|
// Instantiate controller later:
|
|
// This machinery is used to create an instance of the object before calling the
|
|
// controller's constructor itself.
|
|
//
|
|
// This allows properties to be added to the controller before the constructor is
|
|
// invoked. Primarily, this is used for isolate scope bindings in $compile.
|
|
//
|
|
// This feature is not intended for use by applications, and is thus not documented
|
|
// publicly.
|
|
// Object creation: http://jsperf.com/create-constructor/2
|
|
var controllerPrototype = (isArray(expression) ?
|
|
expression[expression.length - 1] : expression).prototype;
|
|
instance = Object.create(controllerPrototype);
|
|
|
|
if (identifier) {
|
|
addIdentifier(locals, identifier, instance, constructor || expression.name);
|
|
}
|
|
|
|
return extend(function() {
|
|
$injector.invoke(expression, instance, locals, constructor);
|
|
return instance;
|
|
}, {
|
|
instance: instance,
|
|
identifier: identifier
|
|
});
|
|
}
|
|
|
|
instance = $injector.instantiate(expression, locals, constructor);
|
|
|
|
if (identifier) {
|
|
addIdentifier(locals, identifier, instance, constructor || expression.name);
|
|
}
|
|
|
|
return instance;
|
|
};
|
|
|
|
function addIdentifier(locals, identifier, instance, name) {
|
|
if (!(locals && isObject(locals.$scope))) {
|
|
throw minErr('$controller')('noscp',
|
|
"Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
|
|
name, identifier);
|
|
}
|
|
|
|
locals.$scope[identifier] = instance;
|
|
}
|
|
}];
|
|
}
|