Skip to content

Commit

Permalink
fix: add decorator and component methods to custom loader
Browse files Browse the repository at this point in the history
  • Loading branch information
Narretz committed Jan 5, 2016
1 parent 560188f commit 55a3747
Showing 1 changed file with 169 additions and 1 deletion.
170 changes: 169 additions & 1 deletion loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,18 @@ function setupModuleLoader(window) {
*/
constant: invokeLater('$provide', 'constant', 'unshift'),

/**
* @ngdoc method
* @name angular.Module#decorator
* @module ng
* @param {string} The name of the service to decorate.
* @param {Function} This function will be invoked when the service needs to be
* instantiated and should return the decorated service instance.
* @description
* See {@link auto.$provide#decorator $provide.decorator()}.
*/
decorator: invokeLaterAndSetModuleName('$provide', 'decorator'),

/**
* @ngdoc method
* @name angular.Module#animation
Expand Down Expand Up @@ -339,7 +351,163 @@ function setupModuleLoader(window) {
* @description
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
directive: invokeLater('$compileProvider', 'directive'),
directive: invokeLaterAndSetModuleName('$compileProvider', 'directive'),

/**
* @ngdoc method
* @name angular.Module#component
* @module ng
* @param {string} name Name of the component in camel-case (i.e. myComp which will match as my-comp)
* @param {Object} options Component definition object (a simplified
* {@link ng.$compile#directive-definition-object directive definition object}),
* has the following properties (all optional):
*
* - `controller` – `{(string|function()=}` – Controller constructor function that should be
* associated with newly created scope or the name of a {@link ng.$compile#-controller-
* registered controller} if passed as a string. Empty function by default.
* - `controllerAs` – `{string=}` – An identifier name for a reference to the controller.
* If present, the controller will be published to scope under the `controllerAs` name.
* If not present, this will default to be the same as the component name.
* - `template` – `{string=|function()=}` – html template as a string or a function that
* returns an html template as a string which should be used as the contents of this component.
* Empty string by default.
*
* If `template` is a function, then it is {@link guide/di injectable}, and receives
* the following locals:
*
* - `$element` - Current element
* - `$attrs` - Current attributes object for the element
*
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
* template that should be used as the contents of this component.
*
* If `templateUrl` is a function, then it is {@link guide/di injectable}, and receives
* the following locals:
*
* - `$element` - Current element
* - `$attrs` - Current attributes object for the element
* - `bindings` – `{object=}` – Define DOM attribute binding to component properties.
* Component properties are always bound to the component controller and not to the scope.
* - `transclude` – `{boolean=}` – Whether {@link $compile#transclusion transclusion} is enabled.
* Disabled by default.
* - `isolate` – `{boolean=}` – Whether the new scope is isolated. Isolated by default.
* - `restrict` - `{string=}` - String of subset of {@link ng.$compile#-restrict- EACM} which
* restricts the component to specific directive declaration style. If omitted, this defaults to 'E'.
* - `$canActivate` – `{function()=}` – TBD.
* - `$routeConfig` – `{object=}` – TBD.
*
* @description
* Register a component definition with the compiler. This is short for registering a specific
* subset of directives which represents actual UI components in your application. Component
* definitions are very simple and do not require the complexity behind defining directives.
* Component definitions usually consist only of the template and the controller backing it.
* In order to make the definition easier, components enforce best practices like controllerAs
* and default behaviors like scope isolation, restrict to elements.
*
* <br />
* Here are a few examples of how you would usually define components:
*
* ```js
* var myMod = angular.module(...);
* myMod.component('myComp', {
* template: '<div>My name is {{myComp.name}}</div>',
* controller: function() {
* this.name = 'shahar';
* }
* });
*
* myMod.component('myComp', {
* template: '<div>My name is {{myComp.name}}</div>',
* bindings: {name: '@'}
* });
*
* myMod.component('myComp', {
* templateUrl: 'views/my-comp.html',
* controller: 'MyCtrl as ctrl',
* bindings: {name: '@'}
* });
*
* ```
*
* <br />
* Components are also useful as route templates (e.g. when using
* {@link ngRoute ngRoute}):
*
* ```js
* var myMod = angular.module('myMod', ['ngRoute']);
*
* myMod.component('home', {
* template: '<h1>Home</h1><p>Hello, {{ home.user.name }} !</p>',
* controller: function() {
* this.user = {name: 'world'};
* }
* });
*
* myMod.config(function($routeProvider) {
* $routeProvider.when('/', {
* template: '<home></home>'
* });
* });
* ```
*
* <br />
* When using {@link ngRoute.$routeProvider $routeProvider}, you can often avoid some
* boilerplate, by assigning the resolved dependencies directly on the route scope:
*
* ```js
* var myMod = angular.module('myMod', ['ngRoute']);
*
* myMod.component('home', {
* template: '<h1>Home</h1><p>Hello, {{ home.user.name }} !</p>',
* bindings: {user: '='}
* });
*
* myMod.config(function($routeProvider) {
* $routeProvider.when('/', {
* template: '<home user="$resolve.user"></home>',
* resolve: {user: function($http) { return $http.get('...'); }}
* });
* });
* ```
*
* <br />
* See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
component: function(name, options) {
function factory($injector) {
function makeInjectable(fn) {
if (isFunction(fn) || Array.isArray(fn)) {
return function(tElement, tAttrs) {
return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});
};
} else {
return fn;
}
}

var template = (!options.template && !options.templateUrl ? '' : options.template);
return {
controller: options.controller || function() {},
controllerAs: identifierForController(options.controller) || options.controllerAs || name,
template: makeInjectable(template),
templateUrl: makeInjectable(options.templateUrl),
transclude: options.transclude === undefined ? false : options.transclude,
scope: options.isolate === false ? true : {},
bindToController: options.bindings || {},
restrict: options.restrict || 'E'
};
}

if (options.$canActivate) {
factory.$canActivate = options.$canActivate;
}
if (options.$routeConfig) {
factory.$routeConfig = options.$routeConfig;
}
factory.$inject = ['$injector'];

return moduleInstance.directive(name, factory);
},

/**
* @ngdoc method
Expand Down

0 comments on commit 55a3747

Please sign in to comment.