@@ -880,8 +880,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
880880 * @param {string|Object } name Name of the directive in camel-case (i.e. <code>ngBind</code> which
881881 * will match as <code>ng-bind</code>), or an object map of directives where the keys are the
882882 * names and the values are the factories.
883- * @param {Function|Array } directiveFactory An injectable directive factory function. See
884- * {@link guide/directive} for more info.
883+ * @param {Function|Array } directiveFactory An injectable directive factory function. See the
884+ * {@link guide/directive directive guide} and the { @link $compile compile API } for more info.
885885 * @returns {ng.$compileProvider } Self for chaining.
886886 */
887887 this . directive = function registerDirective ( name , directiveFactory ) {
@@ -928,6 +928,166 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
928928 return this ;
929929 } ;
930930
931+ /**
932+ * @ngdoc method
933+ * @name $compileProvider#component
934+ * @module ng
935+ * @param {string } name Name of the component in camelCase (i.e. `myComp` which will match `<my-comp>`)
936+ * @param {Object } options Component definition object (a simplified
937+ * {@link ng.$compile#directive-definition-object directive definition object}),
938+ * with the following properties (all optional):
939+ *
940+ * - `controller` – `{(string|function()=}` – controller constructor function that should be
941+ * associated with newly created scope or the name of a {@link ng.$compile#-controller-
942+ * registered controller} if passed as a string. An empty `noop` function by default.
943+ * - `controllerAs` – `{string=}` – identifier name for to reference the controller in the component's scope.
944+ * If present, the controller will be published to scope under the `controllerAs` name.
945+ * If not present, this will default to be the same as the component name.
946+ * - `template` – `{string=|function()=}` – html template as a string or a function that
947+ * returns an html template as a string which should be used as the contents of this component.
948+ * Empty string by default.
949+ *
950+ * If `template` is a function, then it is {@link auto.$injector#invoke injected} with
951+ * the following locals:
952+ *
953+ * - `$element` - Current element
954+ * - `$attrs` - Current attributes object for the element
955+ *
956+ * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
957+ * template that should be used as the contents of this component.
958+ *
959+ * If `templateUrl` is a function, then it is {@link auto.$injector#invoke injected} with
960+ * the following locals:
961+ *
962+ * - `$element` - Current element
963+ * - `$attrs` - Current attributes object for the element
964+ *
965+ * - `bindings` – `{object=}` – defines bindings between DOM attributes and component properties.
966+ * Component properties are always bound to the component controller and not to the scope.
967+ * See {@link ng.$compile#-bindtocontroller- `bindToController`}.
968+ * - `transclude` – `{boolean=}` – whether {@link $compile#transclusion content transclusion} is enabled.
969+ * Disabled by default.
970+ * - `isolate` – `{boolean=}` – whether the new scope is isolated. Isolated by default.
971+ * - `restrict` - `{string=}` - a string containing one or more characters from {@link ng.$compile#-restrict- EACM},
972+ * which restricts the component to specific directive declaration style. If omitted, this defaults to 'E'.
973+ * - `$canActivate` – `{function()=}` – TBD.
974+ * - `$routeConfig` – `{object=}` – TBD.
975+ *
976+ * @returns {ng.$compileProvider } the compile provider itself, for chaining of function calls.
977+ * @description
978+ * Register a **Component definition** with the compiler. This is a shorthand for registering a special
979+ * type of directive, which represents a self-contained UI component in your application.
980+ *
981+ * Component definitions are very simple and do not require much of the complexity behind defining general
982+ * directives. Component definitions usually consist only of a template and a controller backing it.
983+ *
984+ * In order to make the definition easier, components enforce best practices like use of `controllerAs`,
985+ * `bindToController` and default behaviors like **isolate scope** and restriction to elements.
986+ *
987+ * Here are a few examples of how you would usually define components:
988+ *
989+ * ```js
990+ * var myMod = angular.module(...);
991+ * myMod.component('myComp', {
992+ * template: '<div>My name is {{myComp.name}}</div>',
993+ * controller: function() {
994+ * this.name = 'shahar';
995+ * }
996+ * });
997+ *
998+ * myMod.component('myComp', {
999+ * template: '<div>My name is {{myComp.name}}</div>',
1000+ * bindings: {name: '@' }
1001+ * });
1002+ *
1003+ * myMod.component('myComp', {
1004+ * templateUrl: 'views/my-comp.html',
1005+ * controller: 'MyCtrl as ctrl',
1006+ * bindings: {name: '@' }
1007+ * });
1008+ *
1009+ * ```
1010+ *
1011+ * <br />
1012+ * Components are also useful as route templates (e.g. when using
1013+ * {@link ngRoute ngRoute}):
1014+ *
1015+ * ```js
1016+ * var myMod = angular.module('myMod', ['ngRoute']);
1017+ *
1018+ * myMod.component('home', {
1019+ * template: '<h1>Home</h1><p>Hello, {{ home.user.name }} !</p>',
1020+ * controller: function() {
1021+ * this.user = {name: 'world'};
1022+ * }
1023+ * });
1024+ *
1025+ * myMod.config(function($routeProvider) {
1026+ * $routeProvider.when('/', {
1027+ * template: '<home></home>'
1028+ * });
1029+ * });
1030+ * ```
1031+ *
1032+ * <br />
1033+ * When using {@link ngRoute.$routeProvider $routeProvider}, you can often avoid some
1034+ * boilerplate, by assigning the resolved dependencies directly on the route scope:
1035+ *
1036+ * ```js
1037+ * var myMod = angular.module('myMod', ['ngRoute']);
1038+ *
1039+ * myMod.component('home', {
1040+ * template: '<h1>Home</h1><p>Hello, {{ home.user.name }} !</p>',
1041+ * bindings: {user: '='}
1042+ * });
1043+ *
1044+ * myMod.config(function($routeProvider) {
1045+ * $routeProvider.when('/', {
1046+ * template: '<home user="$resolve.user"></home>',
1047+ * resolve: {user: function($http) { return $http.get('...'); }}
1048+ * });
1049+ * });
1050+ * ```
1051+ *
1052+ * <br />
1053+ * See also {@link ng.$compileProvider#directive $compileProvider.directive()}.
1054+ */
1055+ this . component = function registerComponent ( name , options ) {
1056+ function factory ( $injector ) {
1057+ function makeInjectable ( fn ) {
1058+ if ( isFunction ( fn ) || isArray ( fn ) ) {
1059+ return function ( tElement , tAttrs ) {
1060+ return $injector . invoke ( fn , this , { $element : tElement , $attrs : tAttrs } ) ;
1061+ } ;
1062+ } else {
1063+ return fn ;
1064+ }
1065+ }
1066+
1067+ var template = ( ! options . template && ! options . templateUrl ? '' : options . template ) ;
1068+ return {
1069+ controller : options . controller || function ( ) { } ,
1070+ controllerAs : identifierForController ( options . controller ) || options . controllerAs || name ,
1071+ template : makeInjectable ( template ) ,
1072+ templateUrl : makeInjectable ( options . templateUrl ) ,
1073+ transclude : options . transclude ,
1074+ scope : options . isolate === false ? true : { } ,
1075+ bindToController : options . bindings || { } ,
1076+ restrict : options . restrict || 'E'
1077+ } ;
1078+ }
1079+
1080+ if ( options . $canActivate ) {
1081+ factory . $canActivate = options . $canActivate ;
1082+ }
1083+ if ( options . $routeConfig ) {
1084+ factory . $routeConfig = options . $routeConfig ;
1085+ }
1086+ factory . $inject = [ '$injector' ] ;
1087+
1088+ return this . directive ( name , factory ) ;
1089+ } ;
1090+
9311091
9321092 /**
9331093 * @ngdoc method
0 commit comments