build(aio): big move of docs related files (#14361)

All the docs related files (docs-app, doc-gen, content, etc)
are now to be found inside the `/aio` folder.

The related gulp tasks have been moved from the top level
gulp file to a new one inside the `/aio` folder.

The structure of the `/aio` folder now looks like:

```
/aio/
  build/         # gulp tasks
  content/       #MARKDOWN FILES for devguides, cheatsheet, etc
    devguides/
    cheatsheets/
  transforms/    #dgeni packages, templates, etc
  src/
    app/
    assets/
    content/    #HTML + JSON build artifacts produced by dgeni from /aio/content.
                #This dir is .gitignored-ed
  e2e/           #protractor tests for the doc viewer app
  node_modules/ #dependencies for both the doc viewer builds and the dgeni stuff
                #This dir is .gitignored-ed
  gulpfile.js   #Tasks for generating docs and building & deploying the doc viewer
```

Closes #14361
This commit is contained in:
Pete Bacon Darwin
2017-02-09 19:58:36 +00:00
committed by Igor Minar
parent 5e7a2fa854
commit 600402d440
437 changed files with 855 additions and 531 deletions

View File

@ -0,0 +1,18 @@
@cheatsheetSection
Bootstrapping
@cheatsheetIndex 0
@description
{@target ts}`import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';`{@endtarget}
{@target js}Available from the `ng.platformBrowserDynamic` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`platformBrowserDynamic().bootstrapModule(AppModule);`|`platformBrowserDynamic().bootstrapModule`
syntax(js):
`document.addEventListener('DOMContentLoaded', function() {
ng.platformBrowserDynamic
.platformBrowserDynamic()
.bootstrapModule(app.AppModule);
});`|`platformBrowserDynamic().bootstrapModule`
description:
Bootstraps the app, using the root component from the specified `NgModule`. {@target js}Must be wrapped in the event listener to fire when the page loads.{@endtarget}

View File

@ -0,0 +1,34 @@
@cheatsheetSection
Built-in directives
@cheatsheetIndex 3
@description
{@target ts}`import { CommonModule } from '@angular/common';`{@endtarget}
{@target js}Available using the `ng.common.CommonModule` module{@endtarget}
@cheatsheetItem
syntax:
`<section *ngIf="showSection">`|`*ngIf`
description:
Removes or recreates a portion of the DOM tree based on the `showSection` expression.
@cheatsheetItem
syntax:
`<li *ngFor="let item of list">`|`*ngFor`
description:
Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.
@cheatsheetItem
syntax:
`<div [ngSwitch]="conditionExpression">
<template [ngSwitchCase]="case1Exp">...</template>
<template ngSwitchCase="case2LiteralString">...</template>
<template ngSwitchDefault>...</template>
</div>`|`[ngSwitch]`|`[ngSwitchCase]`|`ngSwitchCase`|`ngSwitchDefault`
description:
Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of `conditionExpression`.
@cheatsheetItem
syntax:
`<div [ngClass]="{active: isActive, disabled: isDisabled}">`|`[ngClass]`
description:
Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return {class-name: true/false} map.

View File

@ -0,0 +1,49 @@
@cheatsheetSection
Class decorators
@cheatsheetIndex 5
@description
{@target ts}`import { Directive, ... } from '@angular/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`@Component({...})
class MyComponent() {}`|`@Component({...})`
syntax(js):
`var MyComponent = ng.core.Component({...}).Class({...})`|`ng.core.Component({...})`
description:
Declares that a class is a component and provides metadata about the component.
@cheatsheetItem
syntax(ts):
`@Directive({...})
class MyDirective() {}`|`@Directive({...})`
syntax(js):
`var MyDirective = ng.core.Directive({...}).Class({...})`|`ng.core.Directive({...})`
description:
Declares that a class is a directive and provides metadata about the directive.
@cheatsheetItem
syntax(ts):
`@Pipe({...})
class MyPipe() {}`|`@Pipe({...})`
syntax(js):
`var MyPipe = ng.core.Pipe({...}).Class({...})`|`ng.core.Pipe({...})`
description:
Declares that a class is a pipe and provides metadata about the pipe.
@cheatsheetItem
syntax(ts):
`@Injectable()
class MyService() {}`|`@Injectable()`
syntax(js):
`var OtherService = ng.core.Class(
{constructor: function() { }});
var MyService = ng.core.Class(
{constructor: [OtherService, function(otherService) { }]});`|`var MyService = ng.core.Class({constructor: [OtherService, function(otherService) { }]});`
description:
{@target ts}Declares that a class has dependencies that should be injected into the constructor when the dependency injector is creating an instance of this class.
{@endtarget}
{@target js}
Declares a service to inject into a class by providing an array with the services, with the final item being the function to receive the injected services.
{@endtarget}

View File

@ -0,0 +1,38 @@
@cheatsheetSection
Component configuration
@cheatsheetIndex 7
@description
{@target js}`ng.core.Component` extends `ng.core.Directive`,
so the `ng.core.Directive` configuration applies to components as well{@endtarget}
{@target ts}`@Component` extends `@Directive`,
so the `@Directive` configuration applies to components as well{@endtarget}
@cheatsheetItem
syntax:
`moduleId: module.id`|`moduleId:`
description:
If set, the `templateUrl` and `styleUrl` are resolved relative to the component.
@cheatsheetItem
syntax(ts):
`viewProviders: [MyService, { provide: ... }]`|`viewProviders:`
syntax(js):
`viewProviders: [MyService, { provide: ... }]`|`viewProviders:`
description:
List of dependency injection providers scoped to this component's view.
@cheatsheetItem
syntax:
`template: 'Hello {{name}}'
templateUrl: 'my-component.html'`|`template:`|`templateUrl:`
description:
Inline template or external template URL of the component's view.
@cheatsheetItem
syntax:
`styles: ['.primary {color: red}']
styleUrls: ['my-component.css']`|`styles:`|`styleUrls:`
description:
List of inline CSS styles or external stylesheet URLs for styling the components view.

View File

@ -0,0 +1,30 @@
@cheatsheetSection
Dependency injection configuration
@cheatsheetIndex 10
@description
@cheatsheetItem
syntax(ts):
`{ provide: MyService, useClass: MyMockService }`|`provide`|`useClass`
syntax(js):
`{ provide: MyService, useClass: MyMockService }`|`provide`|`useClass`
description:
Sets or overrides the provider for `MyService` to the `MyMockService` class.
@cheatsheetItem
syntax(ts):
`{ provide: MyService, useFactory: myFactory }`|`provide`|`useFactory`
syntax(js):
`{ provide: MyService, useFactory: myFactory }`|`provide`|`useFactory`
description:
Sets or overrides the provider for `MyService` to the `myFactory` factory function.
@cheatsheetItem
syntax(ts):
`{ provide: MyValue, useValue: 41 }`|`provide`|`useValue`
syntax(js):
`{ provide: MyValue, useValue: 41 }`|`provide`|`useValue`
description:
Sets or overrides the provider for `MyValue` to the value `41`.

View File

@ -0,0 +1,86 @@
@cheatsheetSection
Class field decorators for directives and components
@cheatsheetIndex 8
@description
{@target ts}`import { Input, ... } from '@angular/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`@Input() myProperty;`|`@Input()`
syntax(js):
`ng.core.Input(myProperty, myComponent);`|`ng.core.Input(`|`);`
description:
Declares an input property that you can update via property binding (example:
`<my-cmp [myProperty]="someExpression">`).
@cheatsheetItem
syntax(ts):
`@Output() myEvent = new EventEmitter();`|`@Output()`
syntax(js):
`myEvent = new ng.core.EventEmitter();
ng.core.Output(myEvent, myComponent);`|`ng.core.Output(`|`);`
description:
Declares an output property that fires events that you can subscribe to with an event binding (example: `<my-cmp (myEvent)="doSomething()">`).
@cheatsheetItem
syntax(ts):
`@HostBinding('class.valid') isValid;`|`@HostBinding('class.valid')`
syntax(js):
`ng.core.HostBinding('class.valid',
'isValid', myComponent);`|`ng.core.HostBinding('class.valid', 'isValid'`|`);`
description:
Binds a host element property (here, the CSS class `valid`) to a directive/component property (`isValid`).
@cheatsheetItem
syntax(ts):
`@HostListener('click', ['$event']) onClick(e) {...}`|`@HostListener('click', ['$event'])`
syntax(js):
`ng.core.HostListener('click',
['$event'], onClick(e) {...}, myComponent);`|`ng.core.HostListener('click', ['$event'], onClick(e)`|`);`
description:
Subscribes to a host element event (`click`) with a directive/component method (`onClick`), optionally passing an argument (`$event`).
@cheatsheetItem
syntax(ts):
`@ContentChild(myPredicate) myChildComponent;`|`@ContentChild(myPredicate)`
syntax(js):
`ng.core.ContentChild(myPredicate,
'myChildComponent', myComponent);`|`ng.core.ContentChild(myPredicate,`|`);`
description:
Binds the first result of the component content query (`myPredicate`) to a property (`myChildComponent`) of the class.
@cheatsheetItem
syntax(ts):
`@ContentChildren(myPredicate) myChildComponents;`|`@ContentChildren(myPredicate)`
syntax(js):
`ng.core.ContentChildren(myPredicate,
'myChildComponents', myComponent);`|`ng.core.ContentChildren(myPredicate,`|`);`
description:
Binds the results of the component content query (`myPredicate`) to a property (`myChildComponents`) of the class.
@cheatsheetItem
syntax(ts):
`@ViewChild(myPredicate) myChildComponent;`|`@ViewChild(myPredicate)`
syntax(js):
`ng.core.ViewChild(myPredicate,
'myChildComponent', myComponent);`|`ng.core.ViewChild(myPredicate,`|`);`
description:
Binds the first result of the component view query (`myPredicate`) to a property (`myChildComponent`) of the class. Not available for directives.
@cheatsheetItem
syntax(ts):
`@ViewChildren(myPredicate) myChildComponents;`|`@ViewChildren(myPredicate)`
syntax(js):
`ng.core.ViewChildren(myPredicate,
'myChildComponents', myComponent);`|`ng.core.ViewChildren(myPredicate,`|`);`
description:
Binds the results of the component view query (`myPredicate`) to a property (`myChildComponents`) of the class. Not available for directives.

View File

@ -0,0 +1,23 @@
@cheatsheetSection
Directive configuration
@cheatsheetIndex 6
@description
{@target ts}`@Directive({ property1: value1, ... })`{@endtarget}
{@target js}`ng.core.Directive({ property1: value1, ... }).Class({...})`{@endtarget}
@cheatsheetItem
syntax:
`selector: '.cool-button:not(a)'`|`selector:`
description:
Specifies a CSS selector that identifies this directive within a template. Supported selectors include `element`,
`[attribute]`, `.class`, and `:not()`.
Does not support parent-child relationship selectors.
@cheatsheetItem
syntax(ts):
`providers: [MyService, { provide: ... }]`|`providers:`
syntax(js):
`providers: [MyService, { provide: ... }]`|`providers:`
description:
List of dependency injection providers for this directive and its children.

View File

@ -0,0 +1,12 @@
@cheatsheetSection
Forms
@cheatsheetIndex 4
@description
{@target ts}`import { FormsModule } from '@angular/forms';`{@endtarget}
{@target js}Available using the `ng.forms.FormsModule` module{@endtarget}
@cheatsheetItem
syntax:
`<input [(ngModel)]="userName">`|`[(ngModel)]`
description:
Provides two-way data-binding, parsing, and validation for form controls.

View File

@ -0,0 +1,86 @@
@cheatsheetSection
Directive and component change detection and lifecycle hooks
@cheatsheetIndex 9
@description
{@target ts}(implemented as class methods){@endtarget}
{@target js}(implemented as component properties){@endtarget}
@cheatsheetItem
syntax(ts):
`constructor(myService: MyService, ...) { ... }`|`constructor(myService: MyService, ...)`
syntax(js):
`constructor: function(MyService, ...) { ... }`|`constructor: function(MyService, ...)`
description:
Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.
@cheatsheetItem
syntax(ts):
`ngOnChanges(changeRecord) { ... }`|`ngOnChanges(changeRecord)`
syntax(js):
`ngOnChanges: function(changeRecord) { ... }`|`ngOnChanges: function(changeRecord)`
description:
Called after every change to input properties and before processing content or child views.
@cheatsheetItem
syntax(ts):
`ngOnInit() { ... }`|`ngOnInit()`
syntax(js):
`ngOnInit: function() { ... }`|`ngOnInit: function()`
description:
Called after the constructor, initializing input properties, and the first call to `ngOnChanges`.
@cheatsheetItem
syntax(ts):
`ngDoCheck() { ... }`|`ngDoCheck()`
syntax(js):
`ngDoCheck: function() { ... }`|`ngDoCheck: function()`
description:
Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.
@cheatsheetItem
syntax(ts):
`ngAfterContentInit() { ... }`|`ngAfterContentInit()`
syntax(js):
`ngAfterContentInit: function() { ... }`|`ngAfterContentInit: function()`
description:
Called after `ngOnInit` when the component's or directive's content has been initialized.
@cheatsheetItem
syntax(ts):
`ngAfterContentChecked() { ... }`|`ngAfterContentChecked()`
syntax(js):
`ngAfterContentChecked: function() { ... }`|`ngAfterContentChecked: function()`
description:
Called after every check of the component's or directive's content.
@cheatsheetItem
syntax(ts):
`ngAfterViewInit() { ... }`|`ngAfterViewInit()`
syntax(js):
`ngAfterViewInit: function() { ... }`|`ngAfterViewInit: function()`
description:
Called after `ngAfterContentInit` when the component's view has been initialized. Applies to components only.
@cheatsheetItem
syntax(ts):
`ngAfterViewChecked() { ... }`|`ngAfterViewChecked()`
syntax(js):
`ngAfterViewChecked: function() { ... }`|`ngAfterViewChecked: function()`
description:
Called after every check of the component's view. Applies to components only.
@cheatsheetItem
syntax(ts):
`ngOnDestroy() { ... }`|`ngOnDestroy()`
syntax(js):
`ngOnDestroy: function() { ... }`|`ngOnDestroy: function()`
description:
Called once, before the instance is destroyed.

View File

@ -0,0 +1,58 @@
@cheatsheetSection
NgModules
@cheatsheetIndex 1
@description
{@target ts}`import { NgModule } from '@angular/core';`{@endtarget}
{@target js}Available from the `ng.core` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`@NgModule({ declarations: ..., imports: ...,
exports: ..., providers: ..., bootstrap: ...})
class MyModule {}`|`NgModule`
description:
Defines a module that contains components, directives, pipes, and providers.
syntax(js):
`ng.core.NgModule({declarations: ..., imports: ...,
exports: ..., providers: ..., bootstrap: ...}).
Class({ constructor: function() {}})`
description:
Defines a module that contains components, directives, pipes, and providers.
@cheatsheetItem
syntax:
`declarations: [MyRedComponent, MyBlueComponent, MyDatePipe]`|`declarations:`
description:
List of components, directives, and pipes that belong to this module.
@cheatsheetItem
syntax(ts):
`imports: [BrowserModule, SomeOtherModule]`|`imports:`
description:
List of modules to import into this module. Everything from the imported modules
is available to `declarations` of this module.
syntax(js):
`imports: [ng.platformBrowser.BrowserModule, SomeOtherModule]`|`imports:`
description:
List of modules to import into this module. Everything from the imported modules
is available to `declarations` of this module.
@cheatsheetItem
syntax:
`exports: [MyRedComponent, MyDatePipe]`|`exports:`
description:
List of components, directives, and pipes visible to modules that import this module.
@cheatsheetItem
syntax:
`providers: [MyService, { provide: ... }]`|`providers:`
description:
List of dependency injection providers visible both to the contents of this module and to importers of this module.
@cheatsheetItem
syntax:
`bootstrap: [MyAppComponent]`|`bootstrap:`
description:
List of components to bootstrap when this module is bootstrapped.

View File

@ -0,0 +1,170 @@
@cheatsheetSection
Routing and navigation
@cheatsheetIndex 11
@description
{@target ts}`import { Routes, RouterModule, ... } from '@angular/router';`{@endtarget}
{@target js}Available from the `ng.router` namespace{@endtarget}
@cheatsheetItem
syntax(ts):
`const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'path/:routeParam', component: MyComponent },
{ path: 'staticPath', component: ... },
{ path: '**', component: ... },
{ path: 'oldPath', redirectTo: '/staticPath' },
{ path: ..., component: ..., data: { message: 'Custom' } }
]);
const routing = RouterModule.forRoot(routes);`|`Routes`
syntax(js):
`var routes = [
{ path: '', component: HomeComponent },
{ path: ':routeParam', component: MyComponent },
{ path: 'staticPath', component: ... },
{ path: '**', component: ... },
{ path: 'oldPath', redirectTo: '/staticPath' },
{ path: ..., component: ..., data: { message: 'Custom' } }
]);
var routing = ng.router.RouterModule.forRoot(routes);`|`ng.router.Routes`
description:
Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.
@cheatsheetItem
syntax:
`
<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>
`|`router-outlet`
description:
Marks the location to load the component of the active route.
@cheatsheetItem
syntax:
`
<a routerLink="/path">
<a [routerLink]="[ '/path', routeParam ]">
<a [routerLink]="[ '/path', { matrixParam: 'value' } ]">
<a [routerLink]="[ '/path' ]" [queryParams]="{ page: 1 }">
<a [routerLink]="[ '/path' ]" fragment="anchor">
`|`[routerLink]`
description:
Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the `/` prefix; for a child route, use the `./`prefix; for a sibling or parent, use the `../` prefix.
@cheatsheetItem
syntax:
`<a [routerLink]="[ '/path' ]" routerLinkActive="active">`
description:
The provided classes are added to the element when the `routerLink` becomes the current active route.
@cheatsheetItem
syntax(ts):
`class CanActivateGuard implements CanActivate {
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canActivate: [CanActivateGuard] }`|`CanActivate`
syntax(js):
`var CanActivateGuard = ng.core.Class({
canActivate: function(route, state) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canActivate: [CanActivateGuard] }`|`CanActivate`
description:
An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean or an Observable/Promise that resolves to a boolean.
@cheatsheetItem
syntax(ts):
`class CanDeactivateGuard implements CanDeactivate<T> {
canDeactivate(
component: T,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate`
syntax(js):
`var CanDeactivateGuard = ng.core.Class({
canDeactivate: function(component, route, state) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canDeactivate: [CanDeactivateGuard] }`|`CanDeactivate`
description:
An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean or an Observable/Promise that resolves to a boolean.
@cheatsheetItem
syntax(ts):
`class CanActivateChildGuard implements CanActivateChild {
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canActivateChild: [CanActivateGuard],
children: ... }`|`CanActivateChild`
syntax(js):
`var CanActivateChildGuard = ng.core.Class({
canActivateChild: function(route, state) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canActivateChild: [CanActivateChildGuard],
children: ... }`|`CanActivateChild`
description:
An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean or an Observable/Promise that resolves to a boolean.
@cheatsheetItem
syntax(ts):
`class ResolveGuard implements Resolve<T> {
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any { ... }
}
{ path: ..., resolve: [ResolveGuard] }`|`Resolve`
syntax(js):
`var ResolveGuard = ng.core.Class({
resolve: function(route, state) {
// return Observable/Promise value or value
}
});
{ path: ..., resolve: [ResolveGuard] }`|`Resolve`
description:
An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value.
@cheatsheetItem
syntax(ts):
`class CanLoadGuard implements CanLoad {
canLoad(
route: Route
): Observable<boolean>|Promise<boolean>|boolean { ... }
}
{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad`
syntax(js):
`var CanLoadGuard = ng.core.Class({
canLoad: function(route) {
// return Observable/Promise boolean or boolean
}
});
{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }`|`CanLoad`
description:
An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean or an Observable/Promise that resolves to a boolean.

View File

@ -0,0 +1,94 @@
@cheatsheetSection
Template syntax
@cheatsheetIndex 2
@description
@cheatsheetItem
syntax:
`<input [value]="firstName">`|`[value]`
description:
Binds property `value` to the result of expression `firstName`.
@cheatsheetItem
syntax:
`<div [attr.role]="myAriaRole">`|`[attr.role]`
description:
Binds attribute `role` to the result of expression `myAriaRole`.
@cheatsheetItem
syntax:
`<div [class.extra-sparkle]="isDelightful">`|`[class.extra-sparkle]`
description:
Binds the presence of the CSS class `extra-sparkle` on the element to the truthiness of the expression `isDelightful`.
@cheatsheetItem
syntax:
`<div [style.width.px]="mySize">`|`[style.width.px]`
description:
Binds style property `width` to the result of expression `mySize` in pixels. Units are optional.
@cheatsheetItem
syntax:
`<button (click)="readRainbow($event)">`|`(click)`
description:
Calls method `readRainbow` when a click event is triggered on this button element (or its children) and passes in the event object.
@cheatsheetItem
syntax:
`<div title="Hello {{ponyName}}">`|`{{ponyName}}`
description:
Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to:
`<div [title]="'Hello ' + ponyName">`
@cheatsheetItem
syntax:
`<p>Hello {{ponyName}}</p>`|`{{ponyName}}`
description:
Binds text content to an interpolated string, for example, "Hello Seabiscuit".
@cheatsheetItem
syntax:
`<my-cmp [(title)]="name">`|`[(title)]`
description:
Sets up two-way data binding. Equivalent to: `<my-cmp [title]="name" (titleChange)="name=$event">`
@cheatsheetItem
syntax:
`<video #movieplayer ...>
<button (click)="movieplayer.play()">
</video>`|`#movieplayer`|`(click)`
description:
Creates a local variable `movieplayer` that provides access to the `video` element instance in data-binding and event-binding expressions in the current template.
@cheatsheetItem
syntax:
`<p *myUnless="myExpression">...</p>`|`*myUnless`
description:
The `*` symbol turns the current element into an embedded template. Equivalent to:
`<template [myUnless]="myExpression"><p>...</p></template>`
@cheatsheetItem
syntax:
`<p>Card No.: {{cardNumber | myCardNumberFormatter}}</p>`|`{{cardNumber | myCardNumberFormatter}}`
description:
Transforms the current value of expression `cardNumber` via the pipe called `myCardNumberFormatter`.
@cheatsheetItem
syntax:
`<p>Employer: {{employer?.companyName}}</p>`|`{{employer?.companyName}}`
description:
The safe navigation operator (`?`) means that the `employer` field is optional and if `undefined`, the rest of the expression should be ignored.
@cheatsheetItem
syntax:
`<svg:rect x="0" y="0" width="100" height="100"/>`|`svg:`
description:
An SVG snippet template needs an `svg:` prefix on its root element to disambiguate the SVG element from an HTML component.
@cheatsheetItem
syntax:
`<svg>
<rect x="0" y="0" width="100" height="100"/>
</svg>`|`svg`
description:
An `<svg>` root element is detected as an SVG element automatically, without the prefix.

View File

@ -0,0 +1,160 @@
@title
Component-relative Paths
@intro
Use relative URLs for component templates and styles.
@description
## Write *Component-Relative* URLs to component templates and style files
Our components often refer to external template and style files.
We identify those files with a URL in the `templateUrl` and `styleUrls` properties of the `@Component` metadata
as seen here:
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='absolute-config' -linenums='false' }
By default, we *must* specify the full path back to the application root.
We call this an ***absolute path*** because it is *absolute* with respect to the application root.
There are two problems with an *absolute path*:
1. We have to remember the full path back to the application root.
2. We have to update the URL when we move the component around in the application files structure.
It would be much easier to write and maintain our application components if we could specify template and style locations
*relative* to their component class file.
*We can!*
~~~ {.alert.is-important}
We can if we build our application as `commonjs` modules and load those modules
with a suitable package loader such as `systemjs` or `webpack`.
Learn why [below](#why-default).
The Angular CLI uses these technologies and defaults to the
*component-relative path* approach described here.
CLI users can skip this chapter or read on to understand
how it works.
~~~
## _Component-Relative_ Paths
Our goal is to specify template and style URLs *relative* to their component class files,
hence the term ***component-relative path***.
The key to success is following a convention that puts related component files in well-known locations.
We recommend keeping component template and component-specific style files as *siblings* of their
companion component class files.
Here we see the three files for `SomeComponent` sitting next to each other in the `app` folder.
<aio-file-tree>
<aio-folder>app
<aio-file>some.component.css</aio-file>
<aio-file>some.component.html</aio-file>
<aio-file>some.component.ts</aio-file>
<aio-file>...</aio-file>
</aio-folder>
</aio-file-tree>
We'll have more files and folders &mdash; and greater folder depth &mdash; as our application grows.
We'll be fine as long as the component files travel together as the inseparable siblings they are.
### Set the *moduleId*
Having adopted this file structure convention, we can specify locations of the template and style files
relative to the component class file simply by setting the `moduleId` property of the `@Component` metadata like this
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='module-id' -linenums='false'}
We strip the `app/` base path from the `templateUrl` and `styleUrls` and replace it with `./`.
The result looks like this:
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='relative-config' -linenums='false'}
~~~ {.alert.is-helpful}
Webpack users may prefer [an alternative approach](#webpack).
~~~
## Source
**We can see the <live-example name="cb-component-relative-paths"></live-example>**
and download the source code from there
or simply read the pertinent source here.
<md-tab-group>
<md-tab label="app/some.component.ts">
{@example 'cb-component-relative-paths/ts/app/some.component.ts'}
</md-tab>
<md-tab label="app/some.component.html">
{@example 'cb-component-relative-paths/ts/app/some.component.html'}
</md-tab>
<md-tab label="app/some.component.css">
{@example 'cb-component-relative-paths/ts/app/some.component.css'}
</md-tab>
<md-tab label="app/app.component.ts">
{@example 'cb-component-relative-paths/ts/app/app.component.ts'}
</md-tab>
<md-tab-group>
{@a why-default}
## Appendix: why *component-relative* is not the default
A *component-relative* path is obviously superior to an *absolute* path.
Why did Angular default to the *absolute* path?
Why do *we* have to set the `moduleId`? Why can't Angular set it?
First, let's look at what happens if we use a relative path and omit the `moduleId`.
`EXCEPTION: Failed to load some.component.html`
Angular can't find the file so it throws an error.
Why can't Angular calculate the template and style URLs from the component file's location?
Because the location of the component can't be determined without the developer's help.
Angular apps can be loaded in many ways: from individual files, from SystemJS packages, or
from CommonJS packages, to name a few.
We might generate modules in any of several formats.
We might not be writing modular code at all!
With this diversity of packaging and module load strategies,
it's not possible for Angular to know with certainty where these files reside at runtime.
The only location Angular can be sure of is the URL of the `index.html` home page, the application root.
So by default it resolves template and style paths relative to the URL of `index.html`.
That's why we previously wrote our file URLs with an `app/` base path prefix.
But *if* we follow the recommended guidelines and we write modules in `commonjs` format
and we use a module loader that *plays nice*,
*then* we &mdash; the developers of the application &mdash;
know that the semi-global `module.id` variable is available and contains
the absolute URL of the component class module file.
That knowledge enables us to tell Angular where the *component* file is
by setting the `moduleId`:
{@example 'cb-component-relative-paths/ts/app/some.component.ts' -region='module-id' -linenums='false'}
{@a webpack}
## Webpack: load templates and styles
Webpack developers have an alternative to `moduleId`.
They can load templates and styles at runtime by adding `./` at the beginning of the `template` and `styles` / `styleUrls`
properties that reference *component-relative URLS.
{@example 'webpack/ts/src/app/app.component.ts' --linenums='false'}
Webpack will do a `require` behind the scenes to load the templates and styles. Read more [here](../guide/webpack.html#highlights).
See the [Introduction to Webpack](../guide/webpack.html).

View File

@ -0,0 +1,42 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by, ElementFinder } from 'protractor';
describe('Cookbook: component-relative paths', function () {
interface Page {
title: ElementFinder;
absComp: ElementFinder;
relComp: ElementFinder;
}
function getPageStruct() {
return {
title: element( by.tagName( 'h1' )),
absComp: element( by.css( 'absolute-path div' ) ),
relComp: element( by.css( 'relative-path div' ) )
};
}
let page: Page;
beforeAll(function () {
browser.get('');
page = getPageStruct();
});
it('should display title of the sample', function () {
expect(element(by.tagName('h1')).getText()).toContain('Paths');
});
it('should have absolute-path element', function () {
expect(page.absComp.isPresent()).toBe(true, 'no <absolute-path> element');
});
it('should display the absolute path text', function () {
expect(page.absComp.getText()).toContain('Absolute');
});
it('should display the component-relative path text', function () {
expect(page.relComp.getText()).toContain('Component-relative');
});
});

View File

@ -0,0 +1,12 @@
// #docregion
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template:
`<h1>Absolute & <i>Component-Relative</i> Paths</h1>
<absolute-path></absolute-path>
<relative-path></relative-path>
`
})
export class AppComponent {}

View File

@ -0,0 +1,18 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { SomeAbsoluteComponent, SomeRelativeComponent } from './some.component';
@NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent,
SomeAbsoluteComponent,
SomeRelativeComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }

View File

@ -0,0 +1,5 @@
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);

View File

@ -0,0 +1,22 @@
/* #docregion */
div.absolute {
background: beige;
border: 1px solid darkred;
color: red;
margin: 8px;
max-width: 20em;
padding: 4px;
text-align: center;
}
div.relative {
background: powderblue;
border: 1px solid darkblue;
color: Blue;
font-style: italic;
margin: 8px;
max-width: 20em;
padding: 4px;
text-align: center;
}

View File

@ -0,0 +1,4 @@
<!-- #docregion -->
<div class={{class}}>
{{type}}<br>{{path}}
</div>

View File

@ -0,0 +1,37 @@
// #docregion
import { Component } from '@angular/core';
///////// Using Absolute Paths ///////
// #docregion absolute-config
@Component({
selector: 'absolute-path',
templateUrl: 'app/some.component.html',
styleUrls: ['app/some.component.css']
})
// #enddocregion absolute-config
export class SomeAbsoluteComponent {
class = 'absolute';
type = 'Absolute template & style URLs';
path = 'app/path.component.html';
}
///////// Using Relative Paths ///////
// #docregion relative-config
@Component({
// #docregion module-id
moduleId: module.id,
// #enddocregion module-id
selector: 'relative-path',
templateUrl: './some.component.html',
styleUrls: ['./some.component.css']
})
// #enddocregion relative-config
export class SomeRelativeComponent {
class = 'relative';
type = 'Component-relative template & style URLs';
path = 'path.component.html';
}

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="/">
<title>
Component-Relative Paths
</title>
<!-- #docregion style -->
<link rel="stylesheet" type="text/css" href="styles.css">
<!-- #enddocregion style -->
<!-- Polyfills for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading app...</my-app>
</body>
</html>

View File

@ -0,0 +1,8 @@
{
"description": "Module-relative Paths",
"files": [
"!**/*.d.ts",
"!**/*.js"
],
"tags": [ "cookbook" ]
}

View File

@ -0,0 +1,21 @@
'use strict'; // necessary for es6 output in node
import { browser, element, by } from 'protractor';
describe('QuickStart E2E Tests', function () {
let expectedMsg = 'Hello from Angular App with Webpack';
beforeEach(function () {
browser.get('');
});
it(`should display: ${expectedMsg}`, function () {
expect(element(by.css('h1')).getText()).toEqual(expectedMsg);
});
it('should display an image', function () {
expect(element(by.css('img')).isPresent()).toBe(true);
});
});

View File

@ -0,0 +1,58 @@
/* tslint:disable */
// #docregion one-entry
entry: {
app: 'src/app.ts'
}
// #enddocregion one-entry
// #docregion app-example
import { Component } from '@angular/core';
@Component({
...
})
export class AppComponent {}
// #enddocregion app-example
// #docregion one-output
output: {
filename: 'app.js'
}
// #enddocregion one-output
// #docregion two-entries
entry: {
app: 'src/app.ts',
vendor: 'src/vendor.ts'
},
output: {
filename: '[name].js'
}
// #enddocregion two-entries
// #docregion loaders
rules: [
{
test: /\.ts$/
loader: 'awesome-typescript-loader'
},
{
test: /\.css$/
loaders: 'style-loader!css-loader'
}
]
// #enddocregion loaders
// #docregion imports
// #docregion single-import
import { AppComponent } from './app.component.ts';
// #enddocregion single-import
import 'uiframework/dist/uiframework.css';
// #enddocregion imports
// #docregion plugins
plugins: [
new webpack.optimize.UglifyJsPlugin()
]
// #enddocregion plugins

View File

@ -0,0 +1,5 @@
dist
!karma.webpack.conf.js
!webpack.config.js
!config/*
!public/css/styles.css

View File

@ -0,0 +1,12 @@
// #docregion
var path = require('path');
var _root = path.resolve(__dirname, '..');
function root(args) {
args = Array.prototype.slice.call(arguments, 0);
return path.join.apply(path, [_root].concat(args));
}
exports.root = root;
// #enddocregion

View File

@ -0,0 +1,22 @@
// #docregion
Error.stackTraceLimit = Infinity;
require('core-js/es6');
require('core-js/es7/reflect');
require('zone.js/dist/zone');
require('zone.js/dist/long-stack-trace-zone');
require('zone.js/dist/proxy');
require('zone.js/dist/sync-test');
require('zone.js/dist/jasmine-patch');
require('zone.js/dist/async-test');
require('zone.js/dist/fake-async-test');
var appContext = require.context('../src', true, /\.spec\.ts/);
appContext.keys().forEach(appContext);
var testing = require('@angular/core/testing');
var browser = require('@angular/platform-browser-dynamic/testing');
testing.TestBed.initTestEnvironment(browser.BrowserDynamicTestingModule, browser.platformBrowserDynamicTesting());

View File

@ -0,0 +1,39 @@
// #docregion
var webpackConfig = require('./webpack.test');
module.exports = function (config) {
var _config = {
basePath: '',
frameworks: ['jasmine'],
files: [
{pattern: './config/karma-test-shim.js', watched: false}
],
preprocessors: {
'./config/karma-test-shim.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
stats: 'errors-only'
},
webpackServer: {
noInfo: true
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: false,
browsers: ['PhantomJS'],
singleRun: true
};
config.set(_config);
};
// #enddocregion

View File

@ -0,0 +1,72 @@
// #docregion
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
// #docregion entries
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
// #enddocregion
// #docregion resolve
resolve: {
extensions: ['.ts', '.js']
},
// #enddocregion resolve
// #docregion loaders
module: {
rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file-loader?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract({ fallbackLoader: 'style-loader', loader: 'css-loader?sourceMap' })
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw-loader'
}
]
},
// #enddocregion loaders
// #docregion plugins
plugins: [
// Workaround for angular/angular#11580
new webpack.ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('./src'), // location of your src
{} // a map of your routes
),
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
// #enddocregion plugins
};
// #enddocregion

View File

@ -0,0 +1,26 @@
// #docregion
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
module.exports = webpackMerge(commonConfig, {
devtool: 'cheap-module-eval-source-map',
output: {
path: helpers.root('dist'),
publicPath: 'http://localhost:8080/',
filename: '[name].js',
chunkFilename: '[id].chunk.js'
},
plugins: [
new ExtractTextPlugin('[name].css')
],
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
});
// #enddocregion

View File

@ -0,0 +1,41 @@
// #docregion
var webpack = require('webpack');
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';
module.exports = webpackMerge(commonConfig, {
devtool: 'source-map',
output: {
path: helpers.root('dist'),
publicPath: '/',
filename: '[name].[hash].js',
chunkFilename: '[id].[hash].chunk.js'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.optimize.UglifyJsPlugin({ // https://github.com/angular/angular/issues/10618
mangle: {
keep_fnames: true
}
}),
new ExtractTextPlugin('[name].[hash].css'),
new webpack.DefinePlugin({
'process.env': {
'ENV': JSON.stringify(ENV)
}
}),
new webpack.LoaderOptionsPlugin({
htmlLoader: {
minimize: false // workaround for ng2
}
})
]
});
// #enddocregion

View File

@ -0,0 +1,50 @@
// #docregion
var webpack = require('webpack');
var helpers = require('./helpers');
module.exports = {
devtool: 'inline-source-map',
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html-loader'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'null-loader'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: 'null-loader'
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw-loader'
}
]
},
plugins: [
new webpack.ContextReplacementPlugin(
// The (\\|\/) piece accounts for path separators in *nix and Windows
/angular(\\|\/)core(\\|\/)(esm(\\|\/)src|src)(\\|\/)linker/,
helpers.root('./src'), // location of your src
{} // a map of your routes
)
]
}
// #enddocregion

View File

@ -0,0 +1,4 @@
{
"build": "build:webpack",
"run": "http-server:cli"
}

View File

@ -0,0 +1,2 @@
// #docregion
module.exports = require('./config/karma.conf.js');

View File

@ -0,0 +1,50 @@
{
"name": "angular2-webpack",
"version": "1.0.0",
"description": "A webpack starter for Angular",
"scripts": {
"start": "webpack-dev-server --inline --progress --port 8080",
"test": "karma start",
"build": "rimraf dist && webpack --config config/webpack.prod.js --progress --profile --bail"
},
"license": "MIT",
"dependencies": {
"@angular/common": "~2.4.0",
"@angular/compiler": "~2.4.0",
"@angular/core": "~2.4.0",
"@angular/forms": "~2.4.0",
"@angular/http": "~2.4.0",
"@angular/platform-browser": "~2.4.0",
"@angular/platform-browser-dynamic": "~2.4.0",
"@angular/router": "~3.4.0",
"core-js": "^2.4.1",
"rxjs": "5.0.1",
"zone.js": "^0.7.4"
},
"devDependencies": {
"@types/node": "^6.0.45",
"@types/jasmine": "^2.5.35",
"angular2-template-loader": "^0.6.0",
"awesome-typescript-loader": "^3.0.0-beta.18",
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "2.0.0-beta.5",
"file-loader": "^0.9.0",
"html-loader": "^0.4.3",
"html-webpack-plugin": "^2.16.1",
"jasmine-core": "^2.4.1",
"karma": "^1.2.0",
"karma-jasmine": "^1.0.2",
"karma-phantomjs-launcher": "^1.0.2",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.1",
"null-loader": "^0.1.1",
"phantomjs-prebuilt": "^2.1.7",
"raw-loader": "^0.5.1",
"rimraf": "^2.5.2",
"style-loader": "^0.13.1",
"typescript": "~2.0.10",
"webpack": "2.2.0",
"webpack-dev-server": "2.2.0-rc.0",
"webpack-merge": "^2.4.0"
}
}

View File

@ -0,0 +1,6 @@
/* #docregion */
body {
background: #0147A7;
color: #fff;
}
/* #enddocregion */

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,9 @@
/* #docregion */
main {
padding: 1em;
font-family: Arial, Helvetica, sans-serif;
text-align: center;
margin-top: 50px;
display: block;
}
/* #enddocregion */

View File

@ -0,0 +1,7 @@
<!-- #docregion -->
<main>
<h1>Hello from Angular App with Webpack</h1>
<img src="../../public/images/angular.png">
</main>
<!-- #enddocregion -->

View File

@ -0,0 +1,16 @@
// #docregion
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('App', () => {
beforeEach(() => {
TestBed.configureTestingModule({ declarations: [AppComponent]});
});
it ('should work', () => {
let fixture = TestBed.createComponent(AppComponent);
expect(fixture.componentInstance instanceof AppComponent).toBe(true, 'should create AppComponent');
});
});
// #enddocregion

View File

@ -0,0 +1,12 @@
// #docregion
import { Component } from '@angular/core';
import '../../public/css/styles.css';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }
// #enddocregion

View File

@ -0,0 +1,16 @@
// #docregion
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule { }

View File

@ -0,0 +1,14 @@
<!-- #docregion -->
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>Angular With Webpack</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
<!-- #enddocregion -->

View File

@ -0,0 +1,14 @@
// #docregion
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app/app.module';
// #docregion enable-prod
if (process.env.ENV === 'production') {
enableProdMode();
}
// #enddocregion enable-prod
platformBrowserDynamic().bootstrapModule(AppModule);
// #enddocregion

View File

@ -0,0 +1,12 @@
// #docregion
import 'core-js/es6';
import 'core-js/es7/reflect';
require('zone.js/dist/zone');
if (process.env.ENV === 'production') {
// Production
} else {
// Development and test
Error['stackTraceLimit'] = Infinity;
require('zone.js/dist/long-stack-trace-zone');
}

View File

@ -0,0 +1,15 @@
// #docregion
// Angular
import '@angular/platform-browser';
import '@angular/platform-browser-dynamic';
import '@angular/core';
import '@angular/common';
import '@angular/http';
import '@angular/router';
// RxJS
import 'rxjs';
// Other vendors for example jQuery, Lodash or Bootstrap
// You can import js, ts, css, sass, ...
// #enddocregion

View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
}
}