8000 feat(loader): add convenience method for creating components by shahata · Pull Request #12933 · angular/angular.js · GitHub
[go: up one dir, main page]

Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat(loader): add convenience method for creating components #12933

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
doc updates + adding restrict
  • Loading branch information
Shahar Talmi committed Oct 13, 2015
commit d90f0494907771962f3c6b43e4534259a9eec7cb
59 changes: 46 additions & 13 deletions src/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,16 +287,19 @@ function setupModuleLoader(window) {
* @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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@param {string} name name of the component in canonical camelCase form (i.e. ...

* @param {Object} options Component definition object, has the following properties (all optional):
* @param {Object} options Component definition objec 10000 t (a simplified
* {@link ng.$compile#directive-definition-object directive definition object}),
* has the following properties (all optional):
*
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
* newly created scope or the name of a {@link angular.Module#controller registered
* controller} if passed as a string.
* - `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 auto.$injector#invoke injected} with
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we deviating from the "normal" DDO's template/templateUrl (which don't get injected) ?
There's probably a good reason; I just want to know it :)

Maybe we should stress it more, because more experienced users might get biten by this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is that in module.component there is no factory function. In classic DDO, the template and templateUrl properties are in the closure of the factory function and so have access to injectables from there.

* the following locals:
Expand All @@ -312,18 +315,47 @@ function setupModuleLoader(window) {
*
* - `$element` - Current element
* - `$attrs` - Current attributes object for the element
* - `transclude` – `{boolean=}` – whether {@link $compile#transclusion transclusion} is enabled.
* enabled by default.
* - `isolate` – `{boolean=}` – whether the new scope is isolated. Isolated by default.
* - `bindings` – `{object=}` – define DOM attribute binding to component properties.
* component properties are always bound to the component controller and not to the scope.
* - `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.
* Enabled 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 directive
* where its definition object is isolated, allows transclusion and bound to controller as the
* component name by default.
* 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 and allow transclusion.
*
* Here are a few examples of how you would usually define components:
*
* ```js
* angular.module(...).component.('myComp', {
* template: '<div>My name is {{myComp.name}}</div>',
* controller: function MyCtrl() {
* this.name = 'shahar';
* }
* });
*
* angular.module(...).component.('myComp', {
* template: '<div>My name is {{myComp.name}}</div>',
* bindings: {name: '@'}
* });
*
* angular.module(...).component.('myComp', {
* templateUrl: 'views/my-comp.html',
* controller: 'MyCtrl as ctrl',
* bindings: {name: '@'}
* });
*
* ```
*
* See {@link ng.$compileProvider#directive $compileProvider.directive()}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be more explicit about the reasons why one would use this helper.
We should provide some example usage, including common cases where we rely upon the defaults.

*/
component: function(name, options) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be using invokeLaterAndSetModuleName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a wrapper around module.directive. module.directive will do the invokeLaterAndSetModuleName

Expand All @@ -346,7 +378,8 @@ function setupModuleLoader(window) {
templateUrl: makeInjectable(options.templateUrl),
transclude: options.transclude === undefined ? true : options.transclude,
scope: options.isolate === false ? true : {},
bindToController: options.bindings || {}
bindToController: options.bindings || {},
restrict: options.restrict || 'E'
};
}

Expand Down
9 changes: 6 additions & 3 deletions test/loaderSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ describe('component', function() {
templateUrl: undefined,
transclude: true,
scope: {},
bindToController: {}
bindToController: {},
restrict: 'E'
}));
});
});
Expand All @@ -137,7 +138,8 @@ describe('component', function() {
templateUrl: 'def.html',
transclude: false,
isolate: false,
bindings: {abc: '='}
bindings: {abc: '='},
restrict: 'EA'
});
module('my');
inject(function(myComponentDirective) {
Expand All @@ -148,7 +150,8 @@ describe('component', function() {
templateUrl: 'def.html',
transclude: false,
scope: true,
bindToController: {abc: '='}
bindToController: {abc: '='},
restrict: 'EA'
}));
});
});
Expand Down
0