acq-ng-metadata
Version:
Angular 2 decorators and utils for Angular 1.x
254 lines (168 loc) • 7.91 kB
Markdown
# Function
- [enableProdMode](#enableprodmode)
- [forwardRef](#forwardref)
**Angular 1 container registration helper Methods**
- [provide](#provide) `@deprecated`
- [getInjectableName](#getinjectablename)
- [bundle](#bundle)
---
## enableProdMode
Disable Angular's development mode, which turns off debug data information and optimizes $http calls execution.
Behind the scenes we are setting :
- [`$compileProvider.debugInfoEnabled(false);`](https://docs.angularjs.org/guide/production#disabling-debug-data)
- [`$httpProvider.useApplyAsync(true)`](https://docs.angularjs.org/api/ng/provider/$httpProvider#useApplyAsync)
*example:*
```typescript
// main.ts
import { bootstrap } from 'ng-metadata/platform-browser-dynamic';
import { enableProdMode } from 'ng-metadata/core';
import { AppComponent } from './app.component';
enableProdMode();
bootstrap( AppComponent );
```
###### Parameters
none
returns `undefined`
## forwardRef
Allows to refer to references which are not yet defined.
For instance, `forwardRef` is used when the `token` which we need to refer to for the purposes of DI is declared,
but not yet defined. It is also used when the `token` which we use when creating a query is not yet defined.
###### Parameters
| Parameter | Type | Description |
| ----------------- | ----------------------|------------------------------------------ |
| **forwardRefFn** | `ForwardRefFn` | callback function which returns demanded Injectable |
> ForwardRefFn:
> An interface that a function passed into forwardRef has to implement. `const ref = forwardRef(() => Lock);`
*example:*
```typescript
import * as angular from 'angular';
import { Component, Injectable, Inject, forwardRef, getInjectableName } from 'ng-metadata/core';
@Injectable()
class Door {
lock: Lock;
constructor(@Inject(forwardRef(() => Lock)) lock: Lock) {
this.lock = lock;
}
}
// Only at this point Lock is defined.
@Injectable()
class Lock {}
@Component({
selector: 'my-app',
providers: [Lock, Door]
})
class AppComponent{}
//test.ts
import { expect } from 'chai';
const $injector = angular.injector(['ng','myApp']);
const door = $injector.get(getInjectableName(Door));
expect(door instanceof Door).to.equal(true);
expect(door.lock instanceof Lock).to.equal(true);
```
## provide
> @deprecated, [use component tree composition and provide map literal instead](/docs/recipes/bootstrap.md)
Returns tuple`[name:string,Type:any]` `name` and appropriate `Type` by used decorator.
It's smart ( it knows if argument is Component or Directive or Pipe or Service ).
Has to be used with these `angular.*` methods as first argument via spread because angular methods require 2 args:
- `directive`
- `filter`
- `service`
- `value`
- `constant`
*Example:*
this:
```typescript
import * as angular from 'angular';
import {provide, Component} from 'ng-metadata/core';
@Component({selector:'hero-cmp',template:`<div>hello hero</div>`})
class HeroCmp{}
angular.module('hero',[])
.directive( ...provide(HeroCmp) );
```
will register as `angular.directive('heroCmp', function directiveFactory(){ return {} })`.
> For Services which have @Injectable, by default, it will extract the generated `id` token
so this:
```typescript
import * as angular from 'angular';
import {provide} from 'ng-metadata/core';
import {HeroSvc} from './hero.service';
angular.module('hero',[])
.service( ...provide(HeroSvc) );
```
will register as `angular.service('heroSvc#12', HeroSvc)`
###### Parameters
| Parameter | Type | Description |
| ----------------- | ------------------------------- |------------------------------------------ |
| **token** | `class` or `string` or `OpaqueToken` | class reference or string alias token |
| **provideType?** | `{useClass: class}` or `{useValue: any}` | This is applicable only for angular `service`,`constant`,`value`,`factory`,`provider` methods |
returns tuple [`string`,`factory`] which is registered within angular container.
`useClass` - you have to specify your Class and string which you want to alias it. Note that once you do that, you have to
use this string across whole app
*example:*
```typescript
import * as angular from 'angular';
import {provide, Inject} from 'ng-metadata/core';
class MyService{}
angular.module('myApp')
.constant(...provide('mySvc',{useClass:MyService));
// now when you are injecting the constant in some service or so
export class MyLogger{
constructor(
@Inject('mySvc') private mySvc: MyService
){}
}
```
`useValue` - neat helper if you wanna register values or constants. It is advised to create opaque token for injectable, so you
don't use strings but references
*example:*
```typescript
import * as angular from 'angular';
import {provide, Inject, OpaqueToken} from 'ng-metadata/core';
export const myConstToken = new OpaqueToken('myConstanstYo');
export const myConstants = {foo:123123,moo:'12312'};
angular.module('myApp')
.constant(...provide(myConstToken,{useValue:myConstants));
// now when you are injecting the constant in some service or so
export class MyService{
constructor(
@Inject(myConstToken) private myConst: typeof myConstants
){}
}
```
###### Behind the Scenes
`provide` extract name from various Types, which should be used for registration within angular.* methods.
- for **Injectable** it extraxts `id` property which is generated during class decoration. `id` is auto generated
- for **Component/Directive** it extracts `selector` property and transforms it to camel case
- for **Pipe** it extracts `name` property and transforms it to camel case
- for **Service** it extracts `name` from class property if supported by JS engine, or stringifies function name, and transforms it to camel case
( if useClass used the token overrides default behaviour )
## getInjectableName
A utility function that can be used to get the angular 1 injectable's name. Needed for some cases, since
injectable names are auto-created.
Works for string/OpaqueToken/Type
Note: Type must be decorated with one of class decorators(`@Injectable`,`@Component`,`@Directive`,`@Pipe`), otherwise it throws
*example:*
```typescript
import { Injectable, Component, Pipe, getInjectableName } from 'ng-metadata/core';
// this is given some random name like 'myService48' when it's created with `module.service`
@Injectable
class MyService {}
@Component({selector:'my-cmp',template:'...'})
class MyComponent{}
@Pipe({name:'kebabCase'})
class MyPipe{}
import {expect} from 'chai';
expect(getInjectableName(MyService)).to.equal('myService48');
expect(getInjectableName(MyComponent)).to.equal('myCmp');
expect(getInjectableName(MyPipe)).to.equal('kebabCase');
```
## bundle
Manually bundle component with all it's dependencies registered via `@Component` providers/viewProviders/pipes/directives property metadata.
You may need this when migrating from previous ng-metadata 1.x to Angular 2 component bundling style.
It returns new instance of `ngModule` which can be then registered to other ngModules or provided to `angular.bootstrap`
returns new created `ngModule` instance (if you don't provide existing one as 3rd argument)
| Parameter | Type | Description |
| -------------------| ----------------------|------------------------------------------ |
| **ComponentClass** | `Type` | Component class which is decorated by `@Component` |
| **otherProviders?**| `Array<Type,Function,string>` | you can optionally add other providers manual way ( also function for config phase ) |
| **ngModule?**| `ng.IModule` | you can provide existing ngModule instance, and if you do everything will be registered to this module instead of creating new one |