This commit is contained in:
parent
eff474b5b1
commit
3d12ab7d35
|
@ -11,8 +11,6 @@ table {
|
||||||
margin:20px;
|
margin:20px;
|
||||||
border:#ccc 1px solid;
|
border:#ccc 1px solid;
|
||||||
|
|
||||||
-moz-border-radius:3px;
|
|
||||||
-webkit-border-radius:3px;
|
|
||||||
border-radius:3px;
|
border-radius:3px;
|
||||||
}
|
}
|
||||||
table th {
|
table th {
|
||||||
|
@ -46,12 +44,8 @@ table tr:last-child td {
|
||||||
border-bottom:0;
|
border-bottom:0;
|
||||||
}
|
}
|
||||||
table tr:last-child td:first-child {
|
table tr:last-child td:first-child {
|
||||||
-moz-border-radius-bottomleft:3px;
|
|
||||||
-webkit-border-bottom-left-radius:3px;
|
|
||||||
border-bottom-left-radius:3px;
|
border-bottom-left-radius:3px;
|
||||||
}
|
}
|
||||||
table tr:last-child td:last-child {
|
table tr:last-child td:last-child {
|
||||||
-moz-border-radius-bottomright:3px;
|
|
||||||
-webkit-border-bottom-right-radius:3px;
|
|
||||||
border-bottom-right-radius:3px;
|
border-bottom-right-radius:3px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,9 +67,7 @@
|
||||||
<td>{{movie.hero}}</td>
|
<td>{{movie.hero}}</td>
|
||||||
<td>{{movie.releaseDate | date}}</td>
|
<td>{{movie.releaseDate | date}}</td>
|
||||||
<td>{{movie.mpaa | uppercase}}</td>
|
<td>{{movie.mpaa | uppercase}}</td>
|
||||||
<!-- #docregion currency -->
|
|
||||||
<td>{{movie.price | currency:'USD':true}}</td>
|
<td>{{movie.price | currency:'USD':true}}</td>
|
||||||
<!-- #enddocregion currency -->
|
|
||||||
<td>{{movie.starRating | number:'1.1-2'}}</td>
|
<td>{{movie.starRating | number:'1.1-2'}}</td>
|
||||||
<td>{{movie.approvalRating | percent: '1.0-0'}}</td>
|
<td>{{movie.approvalRating | percent: '1.0-0'}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
/* tslint:disable:no-unused-variable */
|
/* tslint:disable:no-unused-variable */
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion import
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
// #enddocregion import
|
|
||||||
import { IMovie } from './movie';
|
import { IMovie } from './movie';
|
||||||
import { MovieService } from './movie.service';
|
import { MovieService } from './movie.service';
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,6 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
|
||||||
import { Component, HostBinding } from '@angular/core';
|
import { Component, HostBinding } from '@angular/core';
|
||||||
import {
|
|
||||||
trigger,
|
|
||||||
state,
|
|
||||||
style,
|
|
||||||
animate,
|
|
||||||
transition,
|
|
||||||
// ...
|
|
||||||
} from '@angular/animations';
|
|
||||||
|
|
||||||
// #enddocregion imports
|
|
||||||
|
|
||||||
// #docregion decorator, toggle-app-animations
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: 'app.component.html',
|
templateUrl: 'app.component.html',
|
||||||
|
@ -21,15 +9,10 @@ import {
|
||||||
// animation triggers go here
|
// animation triggers go here
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
// #enddocregion decorator
|
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
@HostBinding('@.disabled')
|
@HostBinding('@.disabled') public animationsDisabled = false;
|
||||||
public animationsDisabled = false;
|
|
||||||
// #enddocregion toggle-app-animations
|
|
||||||
|
|
||||||
toggleAnimations() {
|
toggleAnimations() {
|
||||||
this.animationsDisabled = !this.animationsDisabled;
|
this.animationsDisabled = !this.animationsDisabled;
|
||||||
}
|
}
|
||||||
// #docregion toggle-app-animations
|
|
||||||
}
|
}
|
||||||
// #enddocregion toggle-app-animations
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { Hero } from './hero';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hero-list-enter-leave',
|
selector: 'app-hero-list-enter-leave',
|
||||||
// #docregion template
|
|
||||||
template: `
|
template: `
|
||||||
<ul class="heroes">
|
<ul class="heroes">
|
||||||
<li *ngFor="let hero of heroes"
|
<li *ngFor="let hero of heroes"
|
||||||
|
@ -28,7 +27,6 @@ import { Hero } from './hero';
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
`,
|
`,
|
||||||
// #enddocregion template
|
|
||||||
styleUrls: ['./hero-list-page.component.css'],
|
styleUrls: ['./hero-list-page.component.css'],
|
||||||
// #docregion animationdef
|
// #docregion animationdef
|
||||||
animations: [
|
animations: [
|
||||||
|
|
|
@ -62,8 +62,7 @@
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
cursor: hand;
|
font-family: Arial, sans-serif;
|
||||||
font-family: Arial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
|
|
|
@ -1,29 +1,12 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion reusable
|
// #docregion reusable
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { useAnimation, transition, trigger, style, animate } from '@angular/animations';
|
import { transition, trigger, useAnimation } from '@angular/animations';
|
||||||
import { transAnimation } from './animations';
|
import { transAnimation } from './animations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
// #enddocregion reusable
|
|
||||||
selector: 'app-open-close-reusable',
|
selector: 'app-open-close-reusable',
|
||||||
// #docregion runtime
|
|
||||||
animations: [
|
animations: [
|
||||||
transition('open => closed', [
|
|
||||||
style({
|
|
||||||
height: '200 px',
|
|
||||||
opacity: '{{ opacity }}',
|
|
||||||
backgroundcolor: 'yelow'
|
|
||||||
}),
|
|
||||||
animate('{{ time }}'),
|
|
||||||
], {
|
|
||||||
params: {
|
|
||||||
time: '1s',
|
|
||||||
opacity: '1'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
// #enddocregion runtime
|
|
||||||
// #docregion reusable
|
|
||||||
trigger('openClose', [
|
trigger('openClose', [
|
||||||
transition('open => closed', [
|
transition('open => closed', [
|
||||||
useAnimation(transAnimation, {
|
useAnimation(transAnimation, {
|
||||||
|
@ -36,10 +19,9 @@ import { transAnimation } from './animations';
|
||||||
})
|
})
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
// #enddocregion reusable
|
],
|
||||||
templateUrl: 'open-close.component.html',
|
templateUrl: 'open-close.component.html',
|
||||||
styleUrls: ['open-close.component.css']
|
styleUrls: ['open-close.component.css']
|
||||||
// #docregion reusable
|
|
||||||
})
|
})
|
||||||
// #enddocregion reusable
|
// #enddocregion reusable
|
||||||
export class OpenCloseReusableComponent { }
|
export class OpenCloseReusableComponent { }
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
<!-- #docplaster -->
|
|
||||||
<nav>
|
<nav>
|
||||||
<button (click)="toggle()">Toggle Open/Close</button>
|
<button (click)="toggle()">Toggle Open/Close</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<!-- #docregion compare, trigger -->
|
|
||||||
<div [@openClose]="isOpen ? 'open' : 'closed'"
|
<div [@openClose]="isOpen ? 'open' : 'closed'"
|
||||||
(@openClose.start)="onAnimationEvent($event)"
|
(@openClose.start)="onAnimationEvent($event)"
|
||||||
(@openClose.done)="onAnimationEvent($event)"
|
(@openClose.done)="onAnimationEvent($event)"
|
||||||
class="open-close-container">
|
class="open-close-container">
|
||||||
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
|
<p>The box is now {{ isOpen ? 'Open' : 'Closed' }}!</p>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion compare, trigger -->
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
|
||||||
// #docregion component, events1
|
// #docregion component, events1
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-open-close',
|
selector: 'app-open-close',
|
||||||
// #docregion trigger, trigger-wildcard1, trigger-transition
|
// #docregion trigger-wildcard1, trigger-transition
|
||||||
animations: [
|
animations: [
|
||||||
trigger('openClose', [
|
trigger('openClose', [
|
||||||
// #docregion state1
|
// #docregion state1
|
||||||
|
@ -33,7 +33,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
|
||||||
transition('closed => open', [
|
transition('closed => open', [
|
||||||
animate('0.5s')
|
animate('0.5s')
|
||||||
]),
|
]),
|
||||||
// #enddocregion transition2, trigger, component
|
// #enddocregion transition2, component
|
||||||
// #docregion trigger-wildcard1
|
// #docregion trigger-wildcard1
|
||||||
transition('* => closed', [
|
transition('* => closed', [
|
||||||
animate('1s')
|
animate('1s')
|
||||||
|
@ -54,15 +54,14 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
// #enddocregion transition4
|
// #enddocregion transition4
|
||||||
// #docregion transition3
|
|
||||||
transition('* => *', [
|
transition('* => *', [
|
||||||
animate('1s')
|
animate('1s')
|
||||||
]),
|
]),
|
||||||
// #enddocregion transition3, trigger-transition
|
// #enddocregion trigger-transition
|
||||||
// #docregion trigger, component, trigger-wildcard1, events1
|
// #docregion component, trigger-wildcard1, events1
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
// #enddocregion trigger, trigger-wildcard1
|
// #enddocregion trigger-wildcard1
|
||||||
templateUrl: 'open-close.component.html',
|
templateUrl: 'open-close.component.html',
|
||||||
styleUrls: ['open-close.component.css']
|
styleUrls: ['open-close.component.css']
|
||||||
})
|
})
|
||||||
|
|
|
@ -9,6 +9,4 @@ import { Component } from '@angular/core';
|
||||||
<app-sales-tax></app-sales-tax>
|
<app-sales-tax></app-sales-tax>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
// #docregion export
|
|
||||||
export class AppComponent { }
|
export class AppComponent { }
|
||||||
// #enddocregion export
|
|
||||||
|
|
|
@ -22,13 +22,11 @@ import { Logger } from './logger.service';
|
||||||
HeroListComponent,
|
HeroListComponent,
|
||||||
SalesTaxComponent
|
SalesTaxComponent
|
||||||
],
|
],
|
||||||
// #docregion providers
|
|
||||||
providers: [
|
providers: [
|
||||||
BackendService,
|
BackendService,
|
||||||
HeroService,
|
HeroService,
|
||||||
Logger
|
Logger
|
||||||
],
|
],
|
||||||
// #enddocregion providers
|
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
// #docregion export
|
// #docregion export
|
||||||
|
|
|
@ -7,9 +7,7 @@ export class Logger {
|
||||||
log(message: string) { console.log(message); }
|
log(message: string) { console.log(message); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// #docregion import-core-component
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
// #enddocregion import-core-component
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
|
@ -35,9 +33,7 @@ import { BrowserModule } from '@angular/platform-browser';
|
||||||
exports: [ AppComponent ],
|
exports: [ AppComponent ],
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
// #docregion export
|
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
// #enddocregion export
|
|
||||||
// #enddocregion module
|
// #enddocregion module
|
||||||
|
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
<h1>Attribute, class, and style bindings</h1>
|
<h1>Attribute, class, and style bindings</h1>
|
||||||
<h2>Attribute binding</h2>
|
<h2>Attribute binding</h2>
|
||||||
<!-- #docregion attrib-binding-colspan -->
|
|
||||||
<table border=1>
|
<table border=1>
|
||||||
<!-- #docregion colspan -->
|
<!-- #docregion colspan -->
|
||||||
<!-- expression calculates colspan=2 -->
|
<!-- expression calculates colspan=2 -->
|
||||||
|
@ -18,7 +17,6 @@
|
||||||
|
|
||||||
<tr><td>Five</td><td>Six</td></tr>
|
<tr><td>Five</td><td>Six</td></tr>
|
||||||
</table>
|
</table>
|
||||||
<!-- #enddocregion attrib-binding-colspan -->
|
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<!-- #docregion attrib-binding-aria -->
|
<!-- #docregion attrib-binding-aria -->
|
||||||
|
@ -66,4 +64,6 @@
|
||||||
<comp-with-host-binding dirWithHostBinding></comp-with-host-binding>
|
<comp-with-host-binding dirWithHostBinding></comp-with-host-binding>
|
||||||
<!-- #enddocregion style-delegation -->
|
<!-- #enddocregion style-delegation -->
|
||||||
|
|
||||||
|
<!-- #docregion attribute-decorator -->
|
||||||
|
<app-my-input-with-attribute-decorator type="number"></app-my-input-with-attribute-decorator>
|
||||||
|
<!-- #enddocregion attribute-decorator -->
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { CompWithHostBindingComponent } from './comp-with-host-binding.component';
|
import { CompWithHostBindingComponent } from './comp-with-host-binding.component';
|
||||||
|
import { MyInputWithAttributeDecoratorComponent } from './my-input-with-attribute-decorator.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
CompWithHostBindingComponent
|
CompWithHostBindingComponent,
|
||||||
|
MyInputWithAttributeDecoratorComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule
|
BrowserModule
|
||||||
|
|
|
@ -4,11 +4,7 @@
|
||||||
<p appHighlight>Highlight me!</p>
|
<p appHighlight>Highlight me!</p>
|
||||||
<!-- #enddocregion applied -->
|
<!-- #enddocregion applied -->
|
||||||
|
|
||||||
<!-- #docregion color-1 -->
|
|
||||||
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
<p appHighlight highlightColor="yellow">Highlighted in yellow</p>
|
||||||
<p appHighlight [highlightColor]="'orange'">Highlighted in orange</p>
|
<p appHighlight [highlightColor]="'orange'">Highlighted in orange</p>
|
||||||
<!-- #enddocregion color-1 -->
|
|
||||||
|
|
||||||
<!-- #docregion color-2 -->
|
|
||||||
<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p>
|
<p appHighlight [highlightColor]="color">Highlighted with parent component's color</p>
|
||||||
<!-- #enddocregion color-2 -->
|
|
|
@ -1,8 +1,8 @@
|
||||||
/* tslint:disable:no-unused-variable member-ordering */
|
/* tslint:disable:no-unused-variable member-ordering */
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports,
|
// #docregion imports
|
||||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||||
// #enddocregion imports,
|
// #enddocregion imports
|
||||||
import { Input } from '@angular/core';
|
import { Input } from '@angular/core';
|
||||||
// #docregion
|
// #docregion
|
||||||
|
|
||||||
|
@ -10,37 +10,22 @@ import { Input } from '@angular/core';
|
||||||
selector: '[appHighlight]'
|
selector: '[appHighlight]'
|
||||||
})
|
})
|
||||||
export class HighlightDirective {
|
export class HighlightDirective {
|
||||||
// #docregion ctor
|
|
||||||
constructor(private el: ElementRef) { }
|
|
||||||
// #enddocregion ctor
|
|
||||||
|
|
||||||
// #docregion mouse-methods, host
|
constructor(private el: ElementRef) { }
|
||||||
|
|
||||||
|
// #docregion mouse-methods
|
||||||
@HostListener('mouseenter') onMouseEnter() {
|
@HostListener('mouseenter') onMouseEnter() {
|
||||||
// #enddocregion host
|
|
||||||
this.highlight('yellow');
|
this.highlight('yellow');
|
||||||
// #docregion host
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('mouseleave') onMouseLeave() {
|
@HostListener('mouseleave') onMouseLeave() {
|
||||||
// #enddocregion host
|
|
||||||
this.highlight(null);
|
this.highlight(null);
|
||||||
// #docregion host
|
|
||||||
}
|
}
|
||||||
// #enddocregion host
|
|
||||||
|
|
||||||
private highlight(color: string) {
|
private highlight(color: string) {
|
||||||
this.el.nativeElement.style.backgroundColor = color;
|
this.el.nativeElement.style.backgroundColor = color;
|
||||||
}
|
}
|
||||||
// #enddocregion mouse-methods,
|
// #enddocregion mouse-methods
|
||||||
|
|
||||||
// #docregion color
|
|
||||||
@Input() highlightColor: string;
|
|
||||||
// #enddocregion color
|
|
||||||
|
|
||||||
// #docregion color-2
|
|
||||||
@Input() appHighlight: string;
|
|
||||||
// #enddocregion color-2
|
|
||||||
|
|
||||||
// #docregion
|
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -10,13 +10,13 @@ export class HighlightDirective {
|
||||||
|
|
||||||
constructor(private el: ElementRef) { }
|
constructor(private el: ElementRef) { }
|
||||||
|
|
||||||
@Input('appHighlight') highlightColor: string;
|
// #docregion input
|
||||||
|
@Input() appHighlight: string;
|
||||||
|
// #enddocregion input
|
||||||
|
|
||||||
// #docregion mouse-enter
|
|
||||||
@HostListener('mouseenter') onMouseEnter() {
|
@HostListener('mouseenter') onMouseEnter() {
|
||||||
this.highlight(this.highlightColor || 'red');
|
this.highlight(this.appHighlight || 'red');
|
||||||
}
|
}
|
||||||
// #enddocregion mouse-enter
|
|
||||||
|
|
||||||
@HostListener('mouseleave') onMouseLeave() {
|
@HostListener('mouseleave') onMouseLeave() {
|
||||||
this.highlight(null);
|
this.highlight(null);
|
||||||
|
|
|
@ -12,9 +12,7 @@ export class HighlightDirective {
|
||||||
@Input() defaultColor: string;
|
@Input() defaultColor: string;
|
||||||
// #enddocregion defaultColor
|
// #enddocregion defaultColor
|
||||||
|
|
||||||
// #docregion color
|
|
||||||
@Input('appHighlight') highlightColor: string;
|
@Input('appHighlight') highlightColor: string;
|
||||||
// #enddocregion color
|
|
||||||
|
|
||||||
// #docregion mouse-enter
|
// #docregion mouse-enter
|
||||||
@HostListener('mouseenter') onMouseEnter() {
|
@HostListener('mouseenter') onMouseEnter() {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion whole-ngmodule
|
|
||||||
|
|
||||||
// imports
|
// imports
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
@ -32,5 +30,3 @@ import { ItemDirective } from './item.directive';
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
|
||||||
// #enddocregion whole-ngmodule
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ img {
|
||||||
|
|
||||||
.study,
|
.study,
|
||||||
.modified {
|
.modified {
|
||||||
font-family: "Brush Script MT";
|
font-family: "Brush Script MT", cursive;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,8 @@
|
||||||
<fieldset><h4>NgModel examples</h4>
|
<fieldset><h4>NgModel examples</h4>
|
||||||
<p>Current item name: {{currentItem.name}}</p>
|
<p>Current item name: {{currentItem.name}}</p>
|
||||||
<p>
|
<p>
|
||||||
<!-- #docregion without-NgModel -->
|
|
||||||
<label for="without">without NgModel:</label>
|
<label for="without">without NgModel:</label>
|
||||||
<input [value]="currentItem.name" (input)="currentItem.name=$event.target.value" id="without">
|
<input [value]="currentItem.name" (input)="currentItem.name=getValue($event.target)" id="without">
|
||||||
<!-- #enddocregion without-NgModel -->
|
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -27,10 +24,8 @@
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<!-- #docregion NgModelChange -->
|
|
||||||
<label for="example-change">(ngModelChange)="...name=$event":</label>
|
<label for="example-change">(ngModelChange)="...name=$event":</label>
|
||||||
<input [ngModel]="currentItem.name" (ngModelChange)="currentItem.name=$event" id="example-change">
|
<input [ngModel]="currentItem.name" (ngModelChange)="currentItem.name=$event" id="example-change">
|
||||||
<!-- #enddocregion NgModelChange -->
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
@ -77,12 +72,9 @@
|
||||||
|
|
||||||
<!-- NgStyle binding -->
|
<!-- NgStyle binding -->
|
||||||
<hr><h3>NgStyle Binding</h3>
|
<hr><h3>NgStyle Binding</h3>
|
||||||
<!-- #docregion without-ng-style -->
|
|
||||||
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">
|
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">
|
||||||
This div is x-large or smaller.
|
This div is x-large or smaller.
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion without-ng-style -->
|
|
||||||
|
|
||||||
|
|
||||||
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
|
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
|
||||||
<p>currentStyles is {{currentStyles | json}}</p>
|
<p>currentStyles is {{currentStyles | json}}</p>
|
||||||
|
@ -134,7 +126,6 @@
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<h4>Show/hide vs. NgIf</h4>
|
<h4>Show/hide vs. NgIf</h4>
|
||||||
<!-- #docregion NgIf-3 -->
|
|
||||||
<!-- isSpecial is true -->
|
<!-- isSpecial is true -->
|
||||||
<div [class.hidden]="!isSpecial">Show with class</div>
|
<div [class.hidden]="!isSpecial">Show with class</div>
|
||||||
<div [class.hidden]="isSpecial">Hide with class</div>
|
<div [class.hidden]="isSpecial">Hide with class</div>
|
||||||
|
@ -144,7 +135,6 @@
|
||||||
|
|
||||||
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
|
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
|
||||||
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
|
||||||
<!-- #enddocregion NgIf-3 -->
|
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
|
@ -21,7 +21,10 @@ export class AppComponent implements OnInit {
|
||||||
item: Item; // defined to demonstrate template context precedence
|
item: Item; // defined to demonstrate template context precedence
|
||||||
items: Item[];
|
items: Item[];
|
||||||
|
|
||||||
|
// #docregion item
|
||||||
currentItem: Item;
|
currentItem: Item;
|
||||||
|
// #enddocregion item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// trackBy change counting
|
// trackBy change counting
|
||||||
|
@ -111,6 +114,9 @@ export class AppComponent implements OnInit {
|
||||||
|
|
||||||
trackById(index: number, item: any): number { return item.id; }
|
trackById(index: number, item: any): number { return item.id; }
|
||||||
|
|
||||||
|
getValue(target: EventTarget): string {
|
||||||
|
return (target as HTMLInputElement).value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,13 @@ import { Item } from './item';
|
||||||
selector: 'app-stout-item',
|
selector: 'app-stout-item',
|
||||||
template: `I'm a little {{item.name}}, short and stout!`
|
template: `I'm a little {{item.name}}, short and stout!`
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// #docregion input
|
||||||
export class StoutItemComponent {
|
export class StoutItemComponent {
|
||||||
@Input() item: Item;
|
@Input() item: Item;
|
||||||
}
|
}
|
||||||
|
// #enddocregion input
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-best-item',
|
selector: 'app-best-item',
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
|
|
||||||
// #docregion styleurls
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hero-details',
|
selector: 'app-hero-details',
|
||||||
template: `
|
template: `
|
||||||
|
@ -12,7 +11,5 @@ import { Hero } from './hero';
|
||||||
styleUrls: ['./hero-details.component.css']
|
styleUrls: ['./hero-details.component.css']
|
||||||
})
|
})
|
||||||
export class HeroDetailsComponent {
|
export class HeroDetailsComponent {
|
||||||
// #enddocregion styleurls
|
|
||||||
@Input() hero: Hero;
|
@Input() hero: Hero;
|
||||||
// #docregion styleurls
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,10 +5,8 @@ import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
// #docregion
|
// #docregion
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-quest-summary',
|
selector: 'app-quest-summary',
|
||||||
// #docregion urls
|
|
||||||
templateUrl: './quest-summary.component.html',
|
templateUrl: './quest-summary.component.html',
|
||||||
styleUrls: ['./quest-summary.component.css']
|
styleUrls: ['./quest-summary.component.css']
|
||||||
// #enddocregion urls
|
|
||||||
})
|
})
|
||||||
export class QuestSummaryComponent { }
|
export class QuestSummaryComponent { }
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -1,26 +1,18 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
// #docregion import-services
|
|
||||||
import { LoggerService } from './logger.service';
|
import { LoggerService } from './logger.service';
|
||||||
import { UserContextService } from './user-context.service';
|
import { UserContextService } from './user-context.service';
|
||||||
import { UserService } from './user.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
// #enddocregion import-services
|
|
||||||
|
|
||||||
private userId = 1;
|
private userId = 1;
|
||||||
|
|
||||||
// #docregion ctor
|
|
||||||
constructor(logger: LoggerService, public userContext: UserContextService) {
|
constructor(logger: LoggerService, public userContext: UserContextService) {
|
||||||
userContext.loadUser(this.userId);
|
userContext.loadUser(this.userId);
|
||||||
logger.logInfo('AppComponent initialized');
|
logger.logInfo('AppComponent initialized');
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
|
||||||
// #docregion import-services
|
|
||||||
}
|
}
|
||||||
// #enddocregion import-services
|
|
||||||
|
|
|
@ -8,9 +8,7 @@ import { LoggerService } from './logger.service';
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
// #docregion date-logger-service-signature
|
|
||||||
export class DateLoggerService extends LoggerService
|
export class DateLoggerService extends LoggerService
|
||||||
// #enddocregion date-logger-service-signature
|
|
||||||
{
|
{
|
||||||
logInfo(msg: any) { super.logInfo(stamp(msg)); }
|
logInfo(msg: any) { super.logInfo(stamp(msg)); }
|
||||||
logDebug(msg: any) { super.logInfo(stamp(msg)); }
|
logDebug(msg: any) { super.logInfo(stamp(msg)); }
|
||||||
|
|
|
@ -17,11 +17,9 @@ import { LoggerService } from './logger.service';
|
||||||
})
|
})
|
||||||
export class HeroBiosComponent {
|
export class HeroBiosComponent {
|
||||||
// #enddocregion simple
|
// #enddocregion simple
|
||||||
// #docregion ctor
|
|
||||||
constructor(logger: LoggerService) {
|
constructor(logger: LoggerService) {
|
||||||
logger.logInfo('Creating HeroBiosComponent');
|
logger.logInfo('Creating HeroBiosComponent');
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
|
||||||
// #docregion simple
|
// #docregion simple
|
||||||
}
|
}
|
||||||
// #enddocregion simple
|
// #enddocregion simple
|
||||||
|
@ -36,9 +34,7 @@ export class HeroBiosComponent {
|
||||||
<app-hero-bio [heroId]="2"> <app-hero-contact></app-hero-contact> </app-hero-bio>
|
<app-hero-bio [heroId]="2"> <app-hero-contact></app-hero-contact> </app-hero-bio>
|
||||||
<app-hero-bio [heroId]="3"> <app-hero-contact></app-hero-contact> </app-hero-bio>`,
|
<app-hero-bio [heroId]="3"> <app-hero-contact></app-hero-contact> </app-hero-bio>`,
|
||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
// #docregion class-provider
|
|
||||||
providers: [HeroService]
|
providers: [HeroService]
|
||||||
// #enddocregion class-provider
|
|
||||||
})
|
})
|
||||||
export class HeroBiosAndContactsComponent {
|
export class HeroBiosAndContactsComponent {
|
||||||
constructor(logger: LoggerService) {
|
constructor(logger: LoggerService) {
|
||||||
|
|
|
@ -30,9 +30,7 @@ export class HeroContactComponent {
|
||||||
this.hasLogger = true;
|
this.hasLogger = true;
|
||||||
loggerService.logInfo('HeroContactComponent can log!');
|
loggerService.logInfo('HeroContactComponent can log!');
|
||||||
}
|
}
|
||||||
// #docregion ctor
|
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
|
||||||
|
|
||||||
get phoneNumber() { return this.heroCache.hero.phone; }
|
get phoneNumber() { return this.heroCache.hero.phone; }
|
||||||
|
|
||||||
|
|
|
@ -48,13 +48,11 @@ const someHero = new Hero(42, 'Magma', 'Had a great month!', '555-555-5555');
|
||||||
export class HeroOfTheMonthComponent {
|
export class HeroOfTheMonthComponent {
|
||||||
logs: string[] = [];
|
logs: string[] = [];
|
||||||
|
|
||||||
// #docregion ctor-signature
|
|
||||||
constructor(
|
constructor(
|
||||||
logger: MinimalLogger,
|
logger: MinimalLogger,
|
||||||
public heroOfTheMonth: Hero,
|
public heroOfTheMonth: Hero,
|
||||||
@Inject(RUNNERS_UP) public runnersUp: string,
|
@Inject(RUNNERS_UP) public runnersUp: string,
|
||||||
@Inject(TITLE) public title: string)
|
@Inject(TITLE) public title: string)
|
||||||
// #enddocregion ctor-signature
|
|
||||||
{
|
{
|
||||||
this.logs = logger.logs;
|
this.logs = logger.logs;
|
||||||
logger.logInfo('starting up');
|
logger.logInfo('starting up');
|
||||||
|
|
|
@ -35,7 +35,6 @@ export function provideTheParent
|
||||||
|
|
||||||
|
|
||||||
///////// C - Child //////////
|
///////// C - Child //////////
|
||||||
// #docregion carol
|
|
||||||
const templateC = `
|
const templateC = `
|
||||||
<div class="c">
|
<div class="c">
|
||||||
<h3>{{name}}</h3>
|
<h3>{{name}}</h3>
|
||||||
|
@ -54,7 +53,6 @@ export class CarolComponent {
|
||||||
// #enddocregion carol-ctor
|
// #enddocregion carol-ctor
|
||||||
}
|
}
|
||||||
// #enddocregion carol-class
|
// #enddocregion carol-class
|
||||||
// #enddocregion carol
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'chris',
|
selector: 'chris',
|
||||||
|
@ -132,7 +130,7 @@ export class BethComponent implements Parent {
|
||||||
|
|
||||||
///////// A - Grandparent //////
|
///////// A - Grandparent //////
|
||||||
|
|
||||||
// #docregion alex, alex-1
|
// #docregion alex-1
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'alex',
|
selector: 'alex',
|
||||||
template: `
|
template: `
|
||||||
|
@ -157,11 +155,10 @@ export class AlexComponent extends Base
|
||||||
{
|
{
|
||||||
name = 'Alex';
|
name = 'Alex';
|
||||||
}
|
}
|
||||||
// #enddocregion alex, alex-1
|
// #enddocregion alex-1
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
|
||||||
// #docregion alice
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'alice',
|
selector: 'alice',
|
||||||
template: `
|
template: `
|
||||||
|
@ -182,7 +179,6 @@ export class AliceComponent implements Parent
|
||||||
{
|
{
|
||||||
name = 'Alice';
|
name = 'Alice';
|
||||||
}
|
}
|
||||||
// #enddocregion alice
|
|
||||||
|
|
||||||
////// Cathy ///////////
|
////// Cathy ///////////
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,9 +5,7 @@ import { InjectionToken } from '@angular/core';
|
||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
|
|
||||||
// #docregion runners-up
|
|
||||||
export const RUNNERS_UP = new InjectionToken<string>('RunnersUp');
|
export const RUNNERS_UP = new InjectionToken<string>('RunnersUp');
|
||||||
// #enddocregion runners-up
|
|
||||||
|
|
||||||
// #docregion factory-synopsis
|
// #docregion factory-synopsis
|
||||||
export function runnersUpFactory(take: number) {
|
export function runnersUpFactory(take: number) {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { Hero } from './hero';
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
|
|
||||||
/////// HeroesBaseComponent /////
|
/////// HeroesBaseComponent /////
|
||||||
// #docregion heroes-base, injection
|
// #docregion heroes-base
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-unsorted-heroes',
|
selector: 'app-unsorted-heroes',
|
||||||
template: `<div *ngFor="let hero of heroes">{{hero.name}}</div>`,
|
template: `<div *ngFor="let hero of heroes">{{hero.name}}</div>`,
|
||||||
|
@ -14,7 +14,6 @@ import { HeroService } from './hero.service';
|
||||||
})
|
})
|
||||||
export class HeroesBaseComponent implements OnInit {
|
export class HeroesBaseComponent implements OnInit {
|
||||||
constructor(private heroService: HeroService) { }
|
constructor(private heroService: HeroService) { }
|
||||||
// #enddocregion injection
|
|
||||||
|
|
||||||
heroes: Array<Hero>;
|
heroes: Array<Hero>;
|
||||||
|
|
||||||
|
@ -26,9 +25,8 @@ export class HeroesBaseComponent implements OnInit {
|
||||||
// Post-process heroes in derived class override.
|
// Post-process heroes in derived class override.
|
||||||
protected afterGetHeroes() {}
|
protected afterGetHeroes() {}
|
||||||
|
|
||||||
// #docregion injection
|
|
||||||
}
|
}
|
||||||
// #enddocregion heroes-base,injection
|
// #enddocregion heroes-base
|
||||||
|
|
||||||
/////// SortedHeroesComponent /////
|
/////// SortedHeroesComponent /////
|
||||||
// #docregion sorted-heroes
|
// #docregion sorted-heroes
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
// #docregion
|
|
||||||
import { Inject, Injectable, InjectionToken } from '@angular/core';
|
import { Inject, Injectable, InjectionToken } from '@angular/core';
|
||||||
|
|
||||||
// #docregion storage-token
|
|
||||||
export const BROWSER_STORAGE = new InjectionToken<Storage>('Browser Storage', {
|
export const BROWSER_STORAGE = new InjectionToken<Storage>('Browser Storage', {
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
factory: () => localStorage
|
factory: () => localStorage
|
||||||
});
|
});
|
||||||
// #enddocregion storage-token
|
|
||||||
|
|
||||||
// #docregion inject-storage-token
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
@ -31,4 +27,3 @@ export class BrowserStorageService {
|
||||||
this.storage.clear();
|
this.storage.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion inject-storage-token
|
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { LoggerService } from './logger.service';
|
import { LoggerService } from './logger.service';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
// #docregion injectables, injectable
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class UserContextService {
|
export class UserContextService {
|
||||||
// #enddocregion injectables, injectable
|
|
||||||
name: string;
|
name: string;
|
||||||
role: string;
|
role: string;
|
||||||
loggedInSince: Date;
|
loggedInSince: Date;
|
||||||
|
|
||||||
// #docregion ctor, injectables
|
|
||||||
constructor(private userService: UserService, private loggerService: LoggerService) {
|
constructor(private userService: UserService, private loggerService: LoggerService) {
|
||||||
// #enddocregion ctor, injectables
|
|
||||||
this.loggedInSince = new Date();
|
this.loggedInSince = new Date();
|
||||||
// #docregion ctor, injectables
|
|
||||||
}
|
}
|
||||||
// #enddocregion ctor, injectables
|
|
||||||
|
|
||||||
loadUser(userId: number) {
|
loadUser(userId: number) {
|
||||||
const user = this.userService.getUserById(userId);
|
const user = this.userService.getUserById(userId);
|
||||||
|
@ -30,6 +22,4 @@ export class UserContextService {
|
||||||
|
|
||||||
this.loggerService.logDebug('loaded User');
|
this.loggerService.logDebug('loaded User');
|
||||||
}
|
}
|
||||||
// #docregion injectables, injectable
|
|
||||||
}
|
}
|
||||||
// #enddocregion injectables, injectable
|
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
// #docregion
|
|
||||||
// #docregion imports
|
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { APP_CONFIG, AppConfig } from './app.config';
|
import { APP_CONFIG, AppConfig } from './app.config';
|
||||||
// #enddocregion imports
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
|
@ -22,5 +19,3 @@ export class AppComponent {
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
}
|
}
|
||||||
// #enddocregion
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
// #docregion imports
|
|
||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
|
|
||||||
import { APP_CONFIG, AppConfig } from './app.config';
|
import { APP_CONFIG, AppConfig } from './app.config';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
// #enddocregion imports
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
|
@ -28,13 +24,11 @@ import { UserService } from './user.service';
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
||||||
// #docregion ctor
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(APP_CONFIG) config: AppConfig,
|
@Inject(APP_CONFIG) config: AppConfig,
|
||||||
private userService: UserService) {
|
private userService: UserService) {
|
||||||
this.title = config.title;
|
this.title = config.title;
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
|
||||||
|
|
||||||
get isAuthorized() { return this.user.isAuthorized; }
|
get isAuthorized() { return this.user.isAuthorized; }
|
||||||
nextUser() { this.userService.getNewUser(); }
|
nextUser() { this.userService.getNewUser(); }
|
||||||
|
|
|
@ -15,7 +15,6 @@ import { UserService } from './user.service';
|
||||||
|
|
||||||
import { ProvidersModule } from './providers.module';
|
import { ProvidersModule } from './providers.module';
|
||||||
|
|
||||||
// #docregion ngmodule
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -25,14 +24,12 @@ import { ProvidersModule } from './providers.module';
|
||||||
AppComponent,
|
AppComponent,
|
||||||
CarComponent,
|
CarComponent,
|
||||||
HeroesComponent,
|
HeroesComponent,
|
||||||
// #enddocregion ngmodule
|
|
||||||
HeroesTspComponent,
|
HeroesTspComponent,
|
||||||
HeroListComponent,
|
HeroListComponent,
|
||||||
InjectorComponent,
|
InjectorComponent,
|
||||||
TestComponent
|
TestComponent
|
||||||
// #docregion ngmodule
|
|
||||||
],
|
],
|
||||||
// #docregion providers, providers-2
|
// #docregion providers
|
||||||
providers: [
|
providers: [
|
||||||
// #enddocregion providers
|
// #enddocregion providers
|
||||||
Logger,
|
Logger,
|
||||||
|
@ -40,7 +37,7 @@ import { ProvidersModule } from './providers.module';
|
||||||
UserService,
|
UserService,
|
||||||
{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }
|
{ provide: APP_CONFIG, useValue: HERO_DI_CONFIG }
|
||||||
],
|
],
|
||||||
// #enddocregion providers, providers-2
|
// #enddocregion providers
|
||||||
exports: [ CarComponent, HeroesComponent ],
|
exports: [ CarComponent, HeroesComponent ],
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,47 +1,36 @@
|
||||||
// Examples with car and engine variations
|
// Examples with car and engine variations
|
||||||
|
|
||||||
// #docplaster
|
|
||||||
import { Car, Engine, Tires } from './car';
|
import { Car, Engine, Tires } from './car';
|
||||||
|
|
||||||
///////// example 1 ////////////
|
///////// example 1 ////////////
|
||||||
export function simpleCar() {
|
export function simpleCar() {
|
||||||
// #docregion car-ctor-instantiation
|
|
||||||
// Simple car with 4 cylinders and Flintstone tires.
|
// Simple car with 4 cylinders and Flintstone tires.
|
||||||
const car = new Car(new Engine(), new Tires());
|
const car = new Car(new Engine(), new Tires());
|
||||||
// #enddocregion car-ctor-instantiation
|
|
||||||
car.description = 'Simple';
|
car.description = 'Simple';
|
||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////// example 2 ////////////
|
///////// example 2 ////////////
|
||||||
// #docregion car-ctor-instantiation-with-param
|
|
||||||
class Engine2 {
|
class Engine2 {
|
||||||
constructor(public cylinders: number) { }
|
constructor(public cylinders: number) { }
|
||||||
}
|
}
|
||||||
// #enddocregion car-ctor-instantiation-with-param
|
|
||||||
|
|
||||||
export function superCar() {
|
export function superCar() {
|
||||||
// #docregion car-ctor-instantiation-with-param
|
|
||||||
// Super car with 12 cylinders and Flintstone tires.
|
// Super car with 12 cylinders and Flintstone tires.
|
||||||
const bigCylinders = 12;
|
const bigCylinders = 12;
|
||||||
const car = new Car(new Engine2(bigCylinders), new Tires());
|
const car = new Car(new Engine2(bigCylinders), new Tires());
|
||||||
// #enddocregion car-ctor-instantiation-with-param
|
|
||||||
car.description = 'Super';
|
car.description = 'Super';
|
||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////// example 3 //////////
|
/////////// example 3 //////////
|
||||||
// #docregion car-ctor-instantiation-with-mocks
|
|
||||||
class MockEngine extends Engine { cylinders = 8; }
|
class MockEngine extends Engine { cylinders = 8; }
|
||||||
class MockTires extends Tires { make = 'YokoGoodStone'; }
|
class MockTires extends Tires { make = 'YokoGoodStone'; }
|
||||||
|
|
||||||
// #enddocregion car-ctor-instantiation-with-mocks
|
|
||||||
export function testCar() {
|
export function testCar() {
|
||||||
// #docregion car-ctor-instantiation-with-mocks
|
|
||||||
// Test car with 8 cylinders and YokoGoodStone tires.
|
// Test car with 8 cylinders and YokoGoodStone tires.
|
||||||
const car = new Car(new MockEngine(), new MockTires());
|
const car = new Car(new MockEngine(), new MockTires());
|
||||||
// #enddocregion car-ctor-instantiation-with-mocks
|
|
||||||
car.description = 'Test';
|
car.description = 'Test';
|
||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,21 +3,16 @@ import { Injector } from '@angular/core';
|
||||||
import { Car, Engine, Tires } from './car';
|
import { Car, Engine, Tires } from './car';
|
||||||
import { Logger } from '../logger.service';
|
import { Logger } from '../logger.service';
|
||||||
|
|
||||||
// #docregion injector
|
|
||||||
export function useInjector() {
|
export function useInjector() {
|
||||||
let injector: Injector;
|
let injector: Injector;
|
||||||
// #enddocregion injector
|
|
||||||
/*
|
/*
|
||||||
// #docregion injector-no-new
|
|
||||||
// Cannot instantiate an Injector like this!
|
// Cannot instantiate an Injector like this!
|
||||||
let injector = new Injector([
|
let injector = new Injector([
|
||||||
{ provide: Car, deps: [Engine, Tires] },
|
{ provide: Car, deps: [Engine, Tires] },
|
||||||
{ provide: Engine, deps: [] },
|
{ provide: Engine, deps: [] },
|
||||||
{ provide: Tires, deps: [] }
|
{ provide: Tires, deps: [] }
|
||||||
]);
|
]);
|
||||||
// #enddocregion injector-no-new
|
|
||||||
*/
|
*/
|
||||||
// #docregion injector, injector-create-and-call
|
|
||||||
injector = Injector.create({
|
injector = Injector.create({
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: Car, deps: [Engine, Tires] },
|
{ provide: Car, deps: [Engine, Tires] },
|
||||||
|
@ -25,9 +20,7 @@ export function useInjector() {
|
||||||
{ provide: Tires, deps: [] }
|
{ provide: Tires, deps: [] }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
// #docregion injector-call
|
|
||||||
const car = injector.get(Car);
|
const car = injector.get(Car);
|
||||||
// #enddocregion injector-call, injector-create-and-call
|
|
||||||
car.description = 'Injector';
|
car.description = 'Injector';
|
||||||
|
|
||||||
injector = Injector.create({
|
injector = Injector.create({
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
// Car without DI
|
// Car without DI
|
||||||
import { Engine, Tires } from './car';
|
import { Engine, Tires } from './car';
|
||||||
|
|
||||||
// #docregion car
|
|
||||||
export class Car {
|
export class Car {
|
||||||
|
|
||||||
// #docregion car-ctor
|
|
||||||
public engine: Engine;
|
public engine: Engine;
|
||||||
public tires: Tires;
|
public tires: Tires;
|
||||||
public description = 'No DI';
|
public description = 'No DI';
|
||||||
|
@ -13,7 +11,6 @@ export class Car {
|
||||||
this.engine = new Engine();
|
this.engine = new Engine();
|
||||||
this.tires = new Tires();
|
this.tires = new Tires();
|
||||||
}
|
}
|
||||||
// #enddocregion car-ctor
|
|
||||||
|
|
||||||
// Method using the engine and tires
|
// Method using the engine and tires
|
||||||
drive() {
|
drive() {
|
||||||
|
@ -21,4 +18,3 @@ export class Car {
|
||||||
`${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
|
`${this.engine.cylinders} cylinders and ${this.tires.make} tires.`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion car
|
|
||||||
|
|
|
@ -11,11 +11,9 @@ export class Tires {
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class Car {
|
export class Car {
|
||||||
// #docregion car-ctor
|
|
||||||
public description = 'DI';
|
public description = 'DI';
|
||||||
|
|
||||||
constructor(public engine: Engine, public tires: Tires) { }
|
constructor(public engine: Engine, public tires: Tires) { }
|
||||||
// #enddocregion car-ctor
|
|
||||||
|
|
||||||
// Method using the engine and tires
|
// Method using the engine and tires
|
||||||
drive() {
|
drive() {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { HEROES } from './mock-heroes';
|
import { HEROES } from './mock-heroes';
|
||||||
|
|
||||||
|
@ -10,8 +9,6 @@ import { HEROES } from './mock-heroes';
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
// #docregion class
|
|
||||||
export class HeroListComponent {
|
export class HeroListComponent {
|
||||||
heroes = HEROES;
|
heroes = HEROES;
|
||||||
}
|
}
|
||||||
// #enddocregion class
|
|
||||||
|
|
|
@ -22,9 +22,7 @@ import { HeroService } from './hero.service';
|
||||||
export class HeroListComponent {
|
export class HeroListComponent {
|
||||||
heroes: Hero[];
|
heroes: Hero[];
|
||||||
|
|
||||||
// #docregion ctor
|
|
||||||
constructor(heroService: HeroService) {
|
constructor(heroService: HeroService) {
|
||||||
this.heroes = heroService.getHeroes();
|
this.heroes = heroService.getHeroes();
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// #docregion
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HEROES } from './mock-heroes';
|
import { HEROES } from './mock-heroes';
|
||||||
import { Logger } from '../logger.service';
|
import { Logger } from '../logger.service';
|
||||||
|
@ -8,9 +7,7 @@ import { Logger } from '../logger.service';
|
||||||
})
|
})
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
|
|
||||||
// #docregion ctor
|
|
||||||
constructor(private logger: Logger) { }
|
constructor(private logger: Logger) { }
|
||||||
// #enddocregion ctor
|
|
||||||
|
|
||||||
getHeroes() {
|
getHeroes() {
|
||||||
this.logger.log('Getting heroes ...');
|
this.logger.log('Getting heroes ...');
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { Injectable } from '@angular/core';
|
||||||
import { HEROES } from './mock-heroes';
|
import { HEROES } from './mock-heroes';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
// we declare that this service should be created
|
// declares that this service should be created
|
||||||
// by the root application injector.
|
// by the root application injector.
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion, v1
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
// #enddocregion v1
|
|
||||||
import { HeroService } from './hero.service';
|
import { HeroService } from './hero.service';
|
||||||
|
|
||||||
// #docregion v1
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-heroes',
|
selector: 'app-heroes',
|
||||||
// #enddocregion v1
|
|
||||||
providers: [ HeroService ],
|
providers: [ HeroService ],
|
||||||
// #docregion v1
|
|
||||||
template: `
|
template: `
|
||||||
<h2>Heroes</h2>
|
<h2>Heroes</h2>
|
||||||
<app-hero-list></app-hero-list>
|
<app-hero-list></app-hero-list>
|
||||||
|
|
|
@ -8,7 +8,6 @@ import { HeroService } from './heroes/hero.service';
|
||||||
import { heroServiceProvider } from './heroes/hero.service.provider';
|
import { heroServiceProvider } from './heroes/hero.service.provider';
|
||||||
import { Logger } from './logger.service';
|
import { Logger } from './logger.service';
|
||||||
|
|
||||||
// #docregion injector
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-injectors',
|
selector: 'app-injectors',
|
||||||
template: `
|
template: `
|
||||||
|
@ -40,7 +39,6 @@ export class InjectorComponent implements OnInit {
|
||||||
return this.injector.get(ROUS, rousDontExist);
|
return this.injector.get(ROUS, rousDontExist);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion injector
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* R.O.U.S. - Rodents Of Unusual Size
|
* R.O.U.S. - Rodents Of Unusual Size
|
||||||
|
|
|
@ -19,9 +19,9 @@ const template = '{{log}}';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'provider-1',
|
selector: 'provider-1',
|
||||||
template,
|
template,
|
||||||
// #docregion providers-1, providers-logger
|
// #docregion providers-logger
|
||||||
providers: [Logger]
|
providers: [Logger]
|
||||||
// #enddocregion providers-1, providers-logger
|
// #enddocregion providers-logger
|
||||||
})
|
})
|
||||||
export class Provider1Component {
|
export class Provider1Component {
|
||||||
log: string;
|
log: string;
|
||||||
|
@ -114,11 +114,9 @@ export class OldLogger {
|
||||||
selector: 'provider-6a',
|
selector: 'provider-6a',
|
||||||
template,
|
template,
|
||||||
providers:
|
providers:
|
||||||
// #docregion providers-6a
|
|
||||||
[ NewLogger,
|
[ NewLogger,
|
||||||
// Not aliased! Creates two instances of `NewLogger`
|
// Not aliased! Creates two instances of `NewLogger`
|
||||||
{ provide: OldLogger, useClass: NewLogger}]
|
{ provide: OldLogger, useClass: NewLogger}]
|
||||||
// #enddocregion providers-6a
|
|
||||||
})
|
})
|
||||||
export class Provider6aComponent {
|
export class Provider6aComponent {
|
||||||
log: string;
|
log: string;
|
||||||
|
@ -193,9 +191,7 @@ export class Provider8Component {
|
||||||
// must be true else this component would have blown up at runtime
|
// must be true else this component would have blown up at runtime
|
||||||
log = 'Hero service injected successfully via heroServiceProvider';
|
log = 'Hero service injected successfully via heroServiceProvider';
|
||||||
|
|
||||||
// #docregion provider-8-ctor
|
|
||||||
constructor(heroService: HeroService) { }
|
constructor(heroService: HeroService) { }
|
||||||
// #enddocregion provider-8-ctor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
|
@ -221,9 +217,7 @@ export class Provider9Component implements OnInit {
|
||||||
constructor(private config: AppConfig){ }
|
constructor(private config: AppConfig){ }
|
||||||
// #enddocregion provider-9-ctor-interface
|
// #enddocregion provider-9-ctor-interface
|
||||||
*/
|
*/
|
||||||
// #docregion provider-9-ctor
|
|
||||||
constructor(@Inject(APP_CONFIG) private config: AppConfig) { }
|
constructor(@Inject(APP_CONFIG) private config: AppConfig) { }
|
||||||
// #enddocregion provider-9-ctor
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.log = 'APP_CONFIG Application title is ' + this.config.title;
|
this.log = 'APP_CONFIG Application title is ' + this.config.title;
|
||||||
|
@ -233,9 +227,7 @@ export class Provider9Component implements OnInit {
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////
|
||||||
// Sample providers 1 to 7 illustrate a required logger dependency.
|
// Sample providers 1 to 7 illustrate a required logger dependency.
|
||||||
// Optional logger, can be null
|
// Optional logger, can be null
|
||||||
// #docregion import-optional
|
|
||||||
import { Optional } from '@angular/core';
|
import { Optional } from '@angular/core';
|
||||||
// #enddocregion import-optional
|
|
||||||
|
|
||||||
const someMessage = 'Hello from the injected logger';
|
const someMessage = 'Hello from the injected logger';
|
||||||
|
|
||||||
|
@ -246,13 +238,11 @@ const someMessage = 'Hello from the injected logger';
|
||||||
})
|
})
|
||||||
export class Provider10Component implements OnInit {
|
export class Provider10Component implements OnInit {
|
||||||
log: string;
|
log: string;
|
||||||
// #docregion provider-10-ctor
|
|
||||||
constructor(@Optional() private logger?: Logger) {
|
constructor(@Optional() private logger?: Logger) {
|
||||||
if (this.logger) {
|
if (this.logger) {
|
||||||
this.logger.log(someMessage);
|
this.logger.log(someMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion provider-10-ctor
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.log = this.logger ? this.logger.logs[0] : 'Optional logger was not available';
|
this.log = this.logger ? this.logger.logs[0] : 'Optional logger was not available';
|
||||||
|
|
|
@ -22,7 +22,6 @@ export class TestComponent {
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
function runTests() {
|
function runTests() {
|
||||||
|
|
||||||
// #docregion spec
|
|
||||||
const expectedHeroes = [{name: 'A'}, {name: 'B'}]
|
const expectedHeroes = [{name: 'A'}, {name: 'B'}]
|
||||||
const mockService = <HeroService> {getHeroes: () => expectedHeroes }
|
const mockService = <HeroService> {getHeroes: () => expectedHeroes }
|
||||||
|
|
||||||
|
@ -31,7 +30,6 @@ function runTests() {
|
||||||
const component = new HeroListComponent(mockService);
|
const component = new HeroListComponent(mockService);
|
||||||
expect(component.heroes.length).toEqual(expectedHeroes.length);
|
expect(component.heroes.length).toEqual(expectedHeroes.length);
|
||||||
});
|
});
|
||||||
// #enddocregion spec
|
|
||||||
|
|
||||||
return testResults;
|
return testResults;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,4 @@ if (environment.production) {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// #docregion bootstrap
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||||
// #enddocregion bootstrap
|
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { Component } from '@angular/core';
|
||||||
<h2>My favorite hero is: {{myHero}}</h2>
|
<h2>My favorite hero is: {{myHero}}</h2>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
// #docregion class
|
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title: string;
|
title: string;
|
||||||
myHero: string;
|
myHero: string;
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
// #docregion template
|
|
||||||
template: `
|
template: `
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<h2>My favorite hero is: {{myHero}}</h2>
|
<h2>My favorite hero is: {{myHero}}</h2>
|
||||||
`
|
`
|
||||||
// #enddocregion template
|
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'Tour of Heroes';
|
title = 'Tour of Heroes';
|
||||||
|
|
|
@ -1,24 +1,18 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
// #docregion template
|
|
||||||
template: `
|
template: `
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<h2>My favorite hero is: {{myHero}}</h2>
|
<h2>My favorite hero is: {{myHero}}</h2>
|
||||||
<p>Heroes:</p>
|
<p>Heroes:</p>
|
||||||
<ul>
|
<ul>
|
||||||
// #docregion li
|
|
||||||
<li *ngFor="let hero of heroes">
|
<li *ngFor="let hero of heroes">
|
||||||
{{ hero }}
|
{{ hero }}
|
||||||
</li>
|
</li>
|
||||||
// #enddocregion li
|
|
||||||
</ul>
|
</ul>
|
||||||
`
|
`
|
||||||
// #enddocregion template
|
|
||||||
})
|
})
|
||||||
// #docregion class
|
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'Tour of Heroes';
|
title = 'Tour of Heroes';
|
||||||
heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
|
heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
// #docregion import
|
|
||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
// #enddocregion import
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
// #docregion template
|
|
||||||
template: `
|
template: `
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<h2>My favorite hero is: {{myHero.name}}</h2>
|
<h2>My favorite hero is: {{myHero.name}}</h2>
|
||||||
|
@ -18,12 +14,9 @@ import { Hero } from './hero';
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
`
|
`
|
||||||
// #enddocregion template
|
|
||||||
})
|
})
|
||||||
// #docregion class
|
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
title = 'Tour of Heroes';
|
title = 'Tour of Heroes';
|
||||||
// #docregion heroes
|
|
||||||
heroes = [
|
heroes = [
|
||||||
new Hero(1, 'Windstorm'),
|
new Hero(1, 'Windstorm'),
|
||||||
new Hero(13, 'Bombasto'),
|
new Hero(13, 'Bombasto'),
|
||||||
|
@ -31,5 +24,4 @@ export class AppComponent {
|
||||||
new Hero(20, 'Tornado')
|
new Hero(20, 'Tornado')
|
||||||
];
|
];
|
||||||
myHero = this.heroes[0];
|
myHero = this.heroes[0];
|
||||||
// #enddocregion heroes
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion final
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { Hero } from './hero';
|
import { Hero } from './hero';
|
||||||
|
@ -15,9 +13,7 @@ import { Hero } from './hero';
|
||||||
{{ hero.name }}
|
{{ hero.name }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
// #docregion message
|
|
||||||
<p *ngIf="heroes.length > 3">There are many heroes!</p>
|
<p *ngIf="heroes.length > 3">There are many heroes!</p>
|
||||||
// #enddocregion message
|
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
// #docregion
|
|
||||||
export class Hero {
|
export class Hero {
|
||||||
constructor(
|
constructor(
|
||||||
// #docregion id
|
|
||||||
public id: number,
|
public id: number,
|
||||||
// #enddocregion id
|
|
||||||
public name: string) { }
|
public name: string) { }
|
||||||
}
|
}
|
||||||
// #enddocregion
|
|
||||||
|
|
|
@ -7,10 +7,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<!-- #docregion body -->
|
|
||||||
<body>
|
<body>
|
||||||
<app-root></app-root>
|
<app-root></app-root>
|
||||||
</body>
|
</body>
|
||||||
<!-- #enddocregion body -->
|
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
<!-- #docplaster -->
|
|
||||||
<!-- #docregion -->
|
|
||||||
<h1>{{title}}</h1>
|
<h1>{{title}}</h1>
|
||||||
<h2>My Heroes</h2>
|
<h2>My Heroes</h2>
|
||||||
<ul class="heroes">
|
<ul class="heroes">
|
||||||
|
@ -14,8 +12,6 @@
|
||||||
<div><label>id: </label>{{selectedHero.id}}</div>
|
<div><label>id: </label>{{selectedHero.id}}</div>
|
||||||
<div>
|
<div>
|
||||||
<label>name: </label>
|
<label>name: </label>
|
||||||
<!-- #docregion selected-hero -->
|
|
||||||
<input [(ngModel)]="selectedHero.name" placeholder="name"/>
|
<input [(ngModel)]="selectedHero.name" placeholder="name"/>
|
||||||
<!-- #enddocregion selected-hero -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
// #docregion
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
@ -16,9 +15,7 @@ import { AdService } from './ad.service';
|
||||||
HeroJobAdComponent,
|
HeroJobAdComponent,
|
||||||
HeroProfileComponent,
|
HeroProfileComponent,
|
||||||
AdDirective ],
|
AdDirective ],
|
||||||
// #docregion entry-components
|
|
||||||
entryComponents: [ HeroJobAdComponent, HeroProfileComponent ],
|
entryComponents: [ HeroJobAdComponent, HeroProfileComponent ],
|
||||||
// #enddocregion entry-components
|
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
export class AppModule {
|
export class AppModule {
|
||||||
|
|
|
@ -2,13 +2,9 @@
|
||||||
|
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<h3>Target event</h3>
|
<h3>Target event</h3>
|
||||||
<!-- #docregion event-binding-1 -->
|
|
||||||
<button (click)="onSave($event)">Save</button>
|
<button (click)="onSave($event)">Save</button>
|
||||||
<!-- #enddocregion event-binding-1 -->
|
|
||||||
|
|
||||||
<!-- #docregion event-binding-2 -->
|
|
||||||
<button on-click="onSave($event)">on-click Save</button>
|
<button on-click="onSave($event)">on-click Save</button>
|
||||||
<!-- #enddocregion event-binding-2 -->
|
|
||||||
|
|
||||||
<!-- #docregion custom-directive -->
|
<!-- #docregion custom-directive -->
|
||||||
<h4>myClick is an event on the custom ClickDirective:</h4>
|
<h4>myClick is an event on the custom ClickDirective:</h4>
|
||||||
|
@ -24,9 +20,9 @@
|
||||||
|
|
||||||
<!-- #docregion event-binding-3-->
|
<!-- #docregion event-binding-3-->
|
||||||
<input [value]="currentItem.name"
|
<input [value]="currentItem.name"
|
||||||
(input)="currentItem.name=$event.target.value" >
|
(input)="currentItem.name=getValue($event.target)">
|
||||||
without NgModel
|
|
||||||
<!-- #enddocregion event-binding-3-->
|
<!-- #enddocregion event-binding-3-->
|
||||||
|
without NgModel
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="group">
|
<div class="group">
|
||||||
|
|
|
@ -11,7 +11,7 @@ export class AppComponent {
|
||||||
currentItem = { name: 'teapot'} ;
|
currentItem = { name: 'teapot'} ;
|
||||||
clickMessage = '';
|
clickMessage = '';
|
||||||
|
|
||||||
onSave(event?: KeyboardEvent) {
|
onSave(event?: MouseEvent) {
|
||||||
const evtMsg = event ? ' Event target is ' + (event.target as HTMLElement).textContent : '';
|
const evtMsg = event ? ' Event target is ' + (event.target as HTMLElement).textContent : '';
|
||||||
alert('Saved.' + evtMsg);
|
alert('Saved.' + evtMsg);
|
||||||
if (event) { event.stopPropagation(); }
|
if (event) { event.stopPropagation(); }
|
||||||
|
@ -21,9 +21,14 @@ export class AppComponent {
|
||||||
alert(`Delete the ${item.name}.`);
|
alert(`Delete the ${item.name}.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickMe(event?: KeyboardEvent) {
|
onClickMe(event?: MouseEvent) {
|
||||||
const evtMsg = event ? ' Event target class is ' + (event.target as HTMLElement).className : '';
|
const evtMsg = event ? ' Event target class is ' + (event.target as HTMLElement).className : '';
|
||||||
alert('Click me.' + evtMsg);
|
alert('Click me.' + evtMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #docregion getValue
|
||||||
|
getValue(target: EventTarget): string {
|
||||||
|
return (target as HTMLInputElement).value;
|
||||||
|
}
|
||||||
|
// #enddocregion getValue
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion customer-dashboard
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
// #enddocregion customer-dashboard
|
|
||||||
// #docregion customer-dashboard-component
|
// #docregion customer-dashboard-component
|
||||||
// import the new component
|
// import the new component
|
||||||
import { CustomerDashboardComponent } from './customer-dashboard/customer-dashboard.component';
|
import { CustomerDashboardComponent } from './customer-dashboard/customer-dashboard.component';
|
||||||
// #enddocregion customer-dashboard-component
|
|
||||||
|
|
||||||
|
|
||||||
// #docregion customer-dashboard-component
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule
|
CommonModule
|
||||||
|
@ -28,7 +23,4 @@ import { CustomerDashboardComponent } from './customer-dashboard/customer-dashbo
|
||||||
|
|
||||||
// #enddocregion customer-dashboard-component
|
// #enddocregion customer-dashboard-component
|
||||||
|
|
||||||
// #docregion customer-dashboard
|
|
||||||
export class CustomerDashboardModule { }
|
export class CustomerDashboardModule { }
|
||||||
|
|
||||||
// #enddocregion customer-dashboard
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ export class HeroFormReactiveComponent implements OnInit {
|
||||||
heroForm: FormGroup;
|
heroForm: FormGroup;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// #docregion async-validation
|
|
||||||
this.heroForm = new FormGroup({
|
this.heroForm = new FormGroup({
|
||||||
name: new FormControl(this.hero.name, [
|
name: new FormControl(this.hero.name, [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
|
@ -33,7 +32,6 @@ export class HeroFormReactiveComponent implements OnInit {
|
||||||
}),
|
}),
|
||||||
power: new FormControl(this.hero.power, Validators.required)
|
power: new FormControl(this.hero.power, Validators.required)
|
||||||
});
|
});
|
||||||
// #enddocregion async-validation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() { return this.heroForm.get('name'); }
|
get name() { return this.heroForm.get('name'); }
|
||||||
|
@ -42,7 +40,5 @@ export class HeroFormReactiveComponent implements OnInit {
|
||||||
|
|
||||||
get alterEgo() { return this.heroForm.get('alterEgo'); }
|
get alterEgo() { return this.heroForm.get('alterEgo'); }
|
||||||
|
|
||||||
// #docregion async-validation
|
|
||||||
constructor(private alterEgoValidator: UniqueAlterEgoValidator) {}
|
constructor(private alterEgoValidator: UniqueAlterEgoValidator) {}
|
||||||
// #enddocregion async-validation
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
/* #docregion cross-validation-error-css */
|
|
||||||
.cross-validation-error input {
|
.cross-validation-error input {
|
||||||
border-left: 5px solid red;
|
border-left: 5px solid red;
|
||||||
}
|
}
|
||||||
/* #enddocregion cross-validation-error-css */
|
|
|
@ -25,7 +25,6 @@ export class UniqueAlterEgoValidator implements AsyncValidator {
|
||||||
}
|
}
|
||||||
// #enddocregion async-validator
|
// #enddocregion async-validator
|
||||||
|
|
||||||
// #docregion async-validator-directive
|
|
||||||
@Directive({
|
@Directive({
|
||||||
selector: '[appUniqueAlterEgo]',
|
selector: '[appUniqueAlterEgo]',
|
||||||
providers: [
|
providers: [
|
||||||
|
@ -43,4 +42,3 @@ export class UniqueAlterEgoValidatorDirective {
|
||||||
this.validator.validate(control);
|
this.validator.validate(control);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion async-validator-directive
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
|
import { Directive, Input } from '@angular/core';
|
||||||
import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } from '@angular/forms';
|
import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, ValidatorFn } from '@angular/forms';
|
||||||
|
|
||||||
// #docregion custom-validator
|
// #docregion custom-validator
|
||||||
/** A hero's name can't match the given regular expression */
|
/** A hero's name can't match the given regular expression */
|
||||||
|
@ -22,7 +22,7 @@ export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
|
||||||
export class ForbiddenValidatorDirective implements Validator {
|
export class ForbiddenValidatorDirective implements Validator {
|
||||||
@Input('appForbiddenName') forbiddenName: string;
|
@Input('appForbiddenName') forbiddenName: string;
|
||||||
|
|
||||||
validate(control: AbstractControl): {[key: string]: any} | null {
|
validate(control: AbstractControl): ValidationErrors | null {
|
||||||
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
|
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AbstractControl, FormGroup, NG_VALIDATORS, ValidationErrors, Validator,
|
||||||
|
|
||||||
// #docregion cross-validation-validator
|
// #docregion cross-validation-validator
|
||||||
/** A hero's name can't match the hero's alter ego */
|
/** A hero's name can't match the hero's alter ego */
|
||||||
export const identityRevealedValidator: ValidatorFn = (control: FormGroup): ValidationErrors | null => {
|
export const identityRevealedValidator: ValidatorFn = (control: AbstractControl): ValidationErrors | null => {
|
||||||
const name = control.get('name');
|
const name = control.get('name');
|
||||||
const alterEgo = control.get('alterEgo');
|
const alterEgo = control.get('alterEgo');
|
||||||
|
|
||||||
|
|
|
@ -35,13 +35,11 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="alterEgo">Alter Ego</label>
|
<label for="alterEgo">Alter Ego</label>
|
||||||
<!-- #docregion async-validation -->
|
|
||||||
<input id="alterEgo" class="form-control" name="alterEgo"
|
<input id="alterEgo" class="form-control" name="alterEgo"
|
||||||
#alterEgo="ngModel"
|
#alterEgo="ngModel"
|
||||||
[(ngModel)]="hero.alterEgo"
|
[(ngModel)]="hero.alterEgo"
|
||||||
[ngModelOptions]="{ updateOn: 'blur' }"
|
[ngModelOptions]="{ updateOn: 'blur' }"
|
||||||
appUniqueAlterEgo>
|
appUniqueAlterEgo>
|
||||||
<!-- #enddocregion async-validation -->
|
|
||||||
|
|
||||||
<div *ngIf="alterEgo.pending">Validating...</div>
|
<div *ngIf="alterEgo.pending">Validating...</div>
|
||||||
<div *ngIf="alterEgo.invalid" class="alert alert-danger alter-ego-errors">
|
<div *ngIf="alterEgo.invalid" class="alert alert-danger alter-ego-errors">
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
/* tslint:disable: member-ordering */
|
/* tslint:disable: member-ordering */
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
// #docregion component
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-hero-form-template',
|
selector: 'app-hero-form-template',
|
||||||
templateUrl: './hero-form-template.component.html',
|
templateUrl: './hero-form-template.component.html',
|
||||||
|
@ -16,4 +13,3 @@ export class HeroFormTemplateComponent {
|
||||||
hero = {name: 'Dr.', alterEgo: 'Dr. What', power: this.powers[0]};
|
hero = {name: 'Dr.', alterEgo: 'Dr. What', power: this.powers[0]};
|
||||||
|
|
||||||
}
|
}
|
||||||
// #enddocregion
|
|
||||||
|
|
|
@ -102,7 +102,6 @@
|
||||||
|
|
||||||
<!-- ==================================================== -->
|
<!-- ==================================================== -->
|
||||||
<hr>
|
<hr>
|
||||||
<!-- #docregion phase1-->
|
|
||||||
<style>
|
<style>
|
||||||
.no-style .ng-valid {
|
.no-style .ng-valid {
|
||||||
border-left: 1px solid #CCC
|
border-left: 1px solid #CCC
|
||||||
|
@ -113,7 +112,6 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<div class="no-style" style="margin-left: 4px">
|
<div class="no-style" style="margin-left: 4px">
|
||||||
<!-- #docregion start -->
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Hero Form</h1>
|
<h1>Hero Form</h1>
|
||||||
<form>
|
<form>
|
||||||
|
@ -127,7 +125,6 @@
|
||||||
<input type="text" class="form-control" id="alterEgo">
|
<input type="text" class="form-control" id="alterEgo">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- #enddocregion start -->
|
|
||||||
<!-- #docregion powers -->
|
<!-- #docregion powers -->
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="power">Hero Power</label>
|
<label for="power">Hero Power</label>
|
||||||
|
@ -137,17 +134,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- #enddocregion powers -->
|
<!-- #enddocregion powers -->
|
||||||
<!-- #docregion start -->
|
|
||||||
<button type="submit" class="btn btn-success">Submit</button>
|
<button type="submit" class="btn btn-success">Submit</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion start -->
|
|
||||||
<!-- #enddocregion phase1-->
|
|
||||||
|
|
||||||
<!-- ==================================================== -->
|
<!-- ==================================================== -->
|
||||||
<hr>
|
<hr>
|
||||||
<!-- #docregion phase2-->
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>Hero Form</h1>
|
<h1>Hero Form</h1>
|
||||||
<!-- #docregion template-variable-->
|
<!-- #docregion template-variable-->
|
||||||
|
@ -182,7 +175,6 @@
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion phase2-->
|
|
||||||
|
|
||||||
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
|
<!-- EXTRA MATERIAL FOR DOCUMENTATION -->
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -193,11 +185,9 @@
|
||||||
TODO: remove this: {{model.name}}
|
TODO: remove this: {{model.name}}
|
||||||
<!-- #enddocregion ngModelName-1 -->
|
<!-- #enddocregion ngModelName-1 -->
|
||||||
<hr>
|
<hr>
|
||||||
<!-- #docregion ngModel-3-->
|
|
||||||
<input type="text" class="form-control" id="name"
|
<input type="text" class="form-control" id="name"
|
||||||
required
|
required
|
||||||
[ngModel]="model.name" name="name"
|
[ngModel]="model.name" name="name"
|
||||||
(ngModelChange)="model.name = $event">
|
(ngModelChange)="model.name = $event">
|
||||||
TODO: remove this: {{model.name}}
|
TODO: remove this: {{model.name}}
|
||||||
<!-- #enddocregion ngModel-3-->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -49,9 +49,7 @@ export class HeroFormComponent {
|
||||||
// Name via form.controls = {{showFormControls(heroForm)}}
|
// Name via form.controls = {{showFormControls(heroForm)}}
|
||||||
showFormControls(form: any) {
|
showFormControls(form: any) {
|
||||||
return form && form.controls.name &&
|
return form && form.controls.name &&
|
||||||
// #docregion form-controls
|
|
||||||
form.controls.name.value; // Dr. IQ
|
form.controls.name.value; // Dr. IQ
|
||||||
// #enddocregion form-controls
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|
|
@ -7,10 +7,8 @@
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<!-- #docregion bootstrap -->
|
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
|
href="https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css">
|
||||||
<!-- #enddocregion bootstrap -->
|
|
||||||
<!-- #docregion styles -->
|
<!-- #docregion styles -->
|
||||||
<link rel="stylesheet" href="assets/forms.css">
|
<link rel="stylesheet" href="assets/forms.css">
|
||||||
<!-- #enddocregion styles -->
|
<!-- #enddocregion styles -->
|
||||||
|
|
|
@ -1,3 +1 @@
|
||||||
p {
|
|
||||||
font-family: Lato;
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Component } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: [ './app.component.css' ]
|
styleUrls: ['./app.component.css']
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ import { ProductListComponent } from './product-list/product-list.component';
|
||||||
TopBarComponent,
|
TopBarComponent,
|
||||||
ProductListComponent
|
ProductListComponent
|
||||||
],
|
],
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [
|
||||||
|
AppComponent
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
export const products = [
|
export const products = [
|
||||||
{
|
{
|
||||||
|
id: 1,
|
||||||
name: 'Phone XL',
|
name: 'Phone XL',
|
||||||
price: 799,
|
price: 799,
|
||||||
description: 'A large phone with one of the best screens'
|
description: 'A large phone with one of the best screens'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 2,
|
||||||
name: 'Phone Mini',
|
name: 'Phone Mini',
|
||||||
price: 699,
|
price: 699,
|
||||||
description: 'A great phone with one of the best cameras'
|
description: 'A great phone with one of the best cameras'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 3,
|
||||||
name: 'Phone Standard',
|
name: 'Phone Standard',
|
||||||
price: 299,
|
price: 299,
|
||||||
description: ''
|
description: ''
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-top-bar',
|
selector: 'app-top-bar',
|
||||||
templateUrl: './top-bar.component.html',
|
templateUrl: './top-bar.component.html',
|
||||||
styleUrls: ['./top-bar.component.css']
|
styleUrls: ['./top-bar.component.css']
|
||||||
})
|
})
|
||||||
export class TopBarComponent implements OnInit {
|
export class TopBarComponent {
|
||||||
|
|
||||||
constructor() { }
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import { enableProdMode } from '@angular/core';
|
import { enableProdMode } from '@angular/core';
|
||||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
import { environment } from './environments/environment';
|
|
||||||
|
|
||||||
import { AppModule } from './app/app.module';
|
import { AppModule } from './app/app.module';
|
||||||
|
import { environment } from './environments/environment';
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
enableProdMode();
|
enableProdMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||||
|
.catch(err => console.error(err));
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
// #docregion v1
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion import-http
|
// #docregion import-http
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
// #enddocregion import-http
|
// #enddocregion import-http
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
// #docregion props, methods, inject-http, get-shipping
|
// #docregion props, methods, inject-http, get-shipping
|
||||||
export class CartService {
|
export class CartService {
|
||||||
|
// #enddocregion get-shipping
|
||||||
items = [];
|
items = [];
|
||||||
// #enddocregion props, methods
|
// #enddocregion props, methods
|
||||||
|
|
||||||
|
@ -32,8 +33,10 @@ export class CartService {
|
||||||
}
|
}
|
||||||
// #enddocregion methods
|
// #enddocregion methods
|
||||||
|
|
||||||
|
// #docregion get-shipping
|
||||||
getShippingPrices() {
|
getShippingPrices() {
|
||||||
return this.http.get('/assets/shipping.json');
|
return this.http.get<{type: string, price: number}[]>('/assets/shipping.json');
|
||||||
}
|
}
|
||||||
// #docregion props, methods, inject-http
|
// #docregion props, methods, inject-http
|
||||||
}
|
}
|
||||||
|
// #enddocregion props, methods, inject-http
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-cart',
|
selector: 'app-cart',
|
||||||
templateUrl: './cart.component.html',
|
templateUrl: './cart.component.html',
|
||||||
styleUrls: ['./cart.component.css']
|
styleUrls: ['./cart.component.css']
|
||||||
})
|
})
|
||||||
export class CartComponent implements OnInit {
|
export class CartComponent {
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ import { CartService } from '../cart.service';
|
||||||
templateUrl: './cart.component.html',
|
templateUrl: './cart.component.html',
|
||||||
styleUrls: ['./cart.component.css']
|
styleUrls: ['./cart.component.css']
|
||||||
})
|
})
|
||||||
// #docregion inject-cart, items, submit
|
// #docregion inject-cart, items
|
||||||
export class CartComponent {
|
export class CartComponent {
|
||||||
// #enddocregion inject-cart
|
// #enddocregion inject-cart
|
||||||
items;
|
items = this.cartService.getItems();
|
||||||
// #docregion inject-cart
|
// #docregion inject-cart
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
// #docplaster
|
|
||||||
// #docregion imports
|
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion imports
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-cart',
|
selector: 'app-cart',
|
||||||
templateUrl: './cart.component.html',
|
templateUrl: './cart.component.html',
|
||||||
styleUrls: ['./cart.component.css']
|
styleUrls: ['./cart.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props-services, submit
|
|
||||||
export class CartComponent implements OnInit {
|
export class CartComponent implements OnInit {
|
||||||
items;
|
items;
|
||||||
|
|
||||||
|
@ -17,7 +13,7 @@ export class CartComponent implements OnInit {
|
||||||
private cartService: CartService
|
private cartService: CartService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit(): void {
|
||||||
this.items = this.cartService.getItems();
|
this.items = this.cartService.getItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- #docregion checkout-form-1 -->
|
<!-- #docregion checkout-form-1 -->
|
||||||
<form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)">
|
<form [formGroup]="checkoutForm" (ngSubmit)="onSubmit()">
|
||||||
<!-- #enddocregion checkout-form-1 -->
|
<!-- #enddocregion checkout-form-1 -->
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { FormBuilder } from '@angular/forms';
|
import { FormBuilder } from '@angular/forms';
|
||||||
|
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
|
@ -11,38 +11,26 @@ import { CartService } from '../cart.service';
|
||||||
templateUrl: './cart.component.html',
|
templateUrl: './cart.component.html',
|
||||||
styleUrls: ['./cart.component.css']
|
styleUrls: ['./cart.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props-services, submit, inject-form-builder, checkout-form, checkout-form-group
|
// #docregion inject-form-builder, checkout-form-group
|
||||||
export class CartComponent implements OnInit {
|
export class CartComponent {
|
||||||
items;
|
// #enddocregion inject-form-builder
|
||||||
// #enddocregion inject-form-builder
|
items = this.cartService.getItems();
|
||||||
checkoutForm;
|
checkoutForm = this.formBuilder.group({
|
||||||
// #enddocregion checkout-form
|
name: '',
|
||||||
|
address: ''
|
||||||
|
});
|
||||||
// #docregion inject-form-builder
|
// #docregion inject-form-builder
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private cartService: CartService,
|
private cartService: CartService,
|
||||||
private formBuilder: FormBuilder,
|
private formBuilder: FormBuilder,
|
||||||
) {
|
) {}
|
||||||
// #enddocregion inject-form-builder
|
|
||||||
this.checkoutForm = this.formBuilder.group({
|
|
||||||
name: '',
|
|
||||||
address: ''
|
|
||||||
});
|
|
||||||
// #docregion inject-form-builder
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.items = this.cartService.getItems();
|
|
||||||
}
|
|
||||||
// #enddocregion inject-form-builder, checkout-form-group
|
// #enddocregion inject-form-builder, checkout-form-group
|
||||||
|
|
||||||
// #enddocregion props-services
|
onSubmit(): void {
|
||||||
onSubmit(customerData) {
|
|
||||||
// Process checkout data here
|
// Process checkout data here
|
||||||
this.items = this.cartService.clearCart();
|
this.items = this.cartService.clearCart();
|
||||||
|
console.warn('Your order has been submitted', this.checkoutForm.value);
|
||||||
this.checkoutForm.reset();
|
this.checkoutForm.reset();
|
||||||
|
|
||||||
console.warn('Your order has been submitted', customerData);
|
|
||||||
}
|
}
|
||||||
// #docregion props-services, inject-form-builder, checkout-form, checkout-form-group
|
// #docregion inject-form-builder, checkout-form-group
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,10 @@ import { products } from '../products';
|
||||||
templateUrl: './product-details.component.html',
|
templateUrl: './product-details.component.html',
|
||||||
styleUrls: ['./product-details.component.css']
|
styleUrls: ['./product-details.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props-methods, add-to-cart
|
// #docregion props-methods, product-prop
|
||||||
export class ProductDetailsComponent implements OnInit {
|
export class ProductDetailsComponent implements OnInit {
|
||||||
product;
|
product;
|
||||||
|
// #enddocregion product-prop
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
|
@ -22,10 +23,15 @@ export class ProductDetailsComponent implements OnInit {
|
||||||
// #enddocregion props-methods
|
// #enddocregion props-methods
|
||||||
// #docregion get-product
|
// #docregion get-product
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.paramMap.subscribe(params => {
|
// First get the product id from the current route.
|
||||||
this.product = products[+params.get('productId')];
|
const routeParams = this.route.snapshot.paramMap;
|
||||||
});
|
const productIdFromRoute = Number(routeParams.get('productId'));
|
||||||
|
|
||||||
|
// Find the product that correspond with the id provided in route.
|
||||||
|
this.product = products.find(product => product.id === productIdFromRoute);
|
||||||
}
|
}
|
||||||
// #enddocregion get-product
|
// #enddocregion get-product
|
||||||
|
// #docregion product-prop
|
||||||
|
/* ... */
|
||||||
// #docregion props-methods
|
// #docregion props-methods
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports, cart-service
|
// #docregion cart-service
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
import { products } from '../products';
|
import { products } from '../products';
|
||||||
// #enddocregion imports
|
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion cart-service
|
// #enddocregion cart-service
|
||||||
|
|
||||||
|
@ -13,34 +12,31 @@ import { CartService } from '../cart.service';
|
||||||
templateUrl: './product-details.component.html',
|
templateUrl: './product-details.component.html',
|
||||||
styleUrls: ['./product-details.component.css']
|
styleUrls: ['./product-details.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props-methods, get-product, inject-cart-service, add-to-cart
|
// #docregion inject-cart-service, add-to-cart
|
||||||
export class ProductDetailsComponent implements OnInit {
|
export class ProductDetailsComponent implements OnInit {
|
||||||
// #enddocregion add-to-cart, get-product, inject-cart-service
|
// #enddocregion add-to-cart, inject-cart-service
|
||||||
product;
|
product;
|
||||||
|
|
||||||
// #docregion inject-cart-service
|
// #docregion inject-cart-service
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
// #enddocregion props-methods
|
|
||||||
private cartService: CartService
|
private cartService: CartService
|
||||||
// #docregion props-methods
|
|
||||||
) { }
|
) { }
|
||||||
// #enddocregion inject-cart-service
|
// #enddocregion inject-cart-service
|
||||||
|
|
||||||
// #docregion get-product
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
// #enddocregion props-methods
|
// First get the product id from the current route.
|
||||||
this.route.paramMap.subscribe(params => {
|
const routeParams = this.route.snapshot.paramMap;
|
||||||
this.product = products[+params.get('productId')];
|
const productIdFromRoute = Number(routeParams.get('productId'));
|
||||||
});
|
|
||||||
// #docregion props-methods
|
// Find the product that correspond with the id provided in route.
|
||||||
|
this.product = products.find(product => product.id === productIdFromRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion props-methods, get-product
|
|
||||||
// #docregion add-to-cart
|
// #docregion add-to-cart
|
||||||
addToCart(product) {
|
addToCart(product) {
|
||||||
this.cartService.addToCart(product);
|
this.cartService.addToCart(product);
|
||||||
window.alert('Your product has been added to the cart!');
|
window.alert('Your product has been added to the cart!');
|
||||||
}
|
}
|
||||||
// #docregion props-methods, get-product, inject-cart-service
|
// #docregion inject-cart-service
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,11 @@
|
||||||
|
|
||||||
<div *ngFor="let product of products">
|
<div *ngFor="let product of products">
|
||||||
|
|
||||||
<!-- #docregion product-details -->
|
|
||||||
<h3>
|
<h3>
|
||||||
<a [title]="product.name + ' details'">
|
<a [title]="product.name + ' details'">
|
||||||
{{ product.name }}
|
{{ product.name }}
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
<!-- #enddocregion product-details -->
|
|
||||||
|
|
||||||
<p *ngIf="product.description">
|
<p *ngIf="product.description">
|
||||||
Description: {{ product.description }}
|
Description: {{ product.description }}
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
<h2>Products</h2>
|
<h2>Products</h2>
|
||||||
|
|
||||||
<!-- #docregion router-link -->
|
<!-- #docregion router-link -->
|
||||||
<div *ngFor="let product of products; index as productId">
|
<div *ngFor="let product of products">
|
||||||
|
|
||||||
<h3>
|
<h3>
|
||||||
<a [title]="product.name + ' details'" [routerLink]="['/products', productId]">
|
<a [title]="product.name + ' details'" [routerLink]="['/products', product.id]">
|
||||||
{{ product.name }}
|
{{ product.name }}
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
<!-- #enddocregion router-link -->
|
|
||||||
|
<!-- #enddocregion router-link -->
|
||||||
<p *ngIf="product.description">
|
<p *ngIf="product.description">
|
||||||
Description: {{ product.description }}
|
Description: {{ product.description }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button (click)="share()">
|
<button (click)="share()">
|
||||||
Share
|
Share
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<app-product-alerts
|
<app-product-alerts
|
||||||
[product]="product"
|
[product]="product"
|
||||||
(notify)="onNotify()">
|
(notify)="onNotify()">
|
||||||
</app-product-alerts>
|
</app-product-alerts>
|
||||||
<!-- #docregion router-link -->
|
<!-- #docregion router-link -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion router-link -->
|
<!-- #enddocregion router-link -->
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
export const products = [
|
export const products = [
|
||||||
{
|
{
|
||||||
|
id: 1,
|
||||||
name: 'Phone XL',
|
name: 'Phone XL',
|
||||||
price: 799,
|
price: 799,
|
||||||
description: 'A large phone with one of the best screens'
|
description: 'A large phone with one of the best screens'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 2,
|
||||||
name: 'Phone Mini',
|
name: 'Phone Mini',
|
||||||
price: 699,
|
price: 699,
|
||||||
description: 'A great phone with one of the best cameras'
|
description: 'A great phone with one of the best cameras'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: 3,
|
||||||
name: 'Phone Standard',
|
name: 'Phone Standard',
|
||||||
price: 299,
|
price: 299,
|
||||||
description: ''
|
description: ''
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-shipping',
|
selector: 'app-shipping',
|
||||||
templateUrl: './shipping.component.html',
|
templateUrl: './shipping.component.html',
|
||||||
styleUrls: ['./shipping.component.css']
|
styleUrls: ['./shipping.component.css']
|
||||||
})
|
})
|
||||||
export class ShippingComponent implements OnInit {
|
export class ShippingComponent {
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { CartService } from '../cart.service';
|
import { CartService } from '../cart.service';
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -10,21 +10,18 @@ import { CartService } from '../cart.service';
|
||||||
templateUrl: './shipping.component.html',
|
templateUrl: './shipping.component.html',
|
||||||
styleUrls: ['./shipping.component.css']
|
styleUrls: ['./shipping.component.css']
|
||||||
})
|
})
|
||||||
// #docregion props, ctor
|
// #docregion props
|
||||||
export class ShippingComponent implements OnInit {
|
export class ShippingComponent {
|
||||||
shippingCosts;
|
shippingCosts = this.cartService.getShippingPrices();
|
||||||
// #enddocregion props
|
// #enddocregion props
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #docregion inject-cart-service
|
// #docregion inject-cart-service
|
||||||
constructor(
|
constructor(private cartService: CartService) {
|
||||||
private cartService: CartService
|
|
||||||
) {
|
|
||||||
}
|
}
|
||||||
// #enddocregion inject-cart-service
|
// #enddocregion inject-cart-service
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.shippingCosts = this.cartService.getShippingPrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
// #docregion props
|
// #docregion props
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,26 @@ const checkLogForMessage = async (message: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('Http Tests', () => {
|
describe('Http Tests', () => {
|
||||||
|
// It seems that currently Chrome/ChromeDriver fail to click a button that is just outside the
|
||||||
|
// viewport (or maybe only partially inside the viewport) - at least in headless mode.
|
||||||
|
// Possible solutions:
|
||||||
|
// 1. Click the element via JavaScript (with something like
|
||||||
|
// `browser.executeScript('arguments[0].click', elem)`).
|
||||||
|
// 2. Manually scroll the element into view before clicking:
|
||||||
|
// https://stackoverflow.com/questions/47776774/element-is-not-clickable-at-point-in-headless-mode-but-when-we-remove-headless
|
||||||
|
// 3. Explicitly set the window size to a bigger size:
|
||||||
|
// https://stackoverflow.com/questions/62003082/elementnotinteractableexception-element-not-interactable-element-has-zero-size
|
||||||
|
//
|
||||||
|
// Since the default 800x600 window size in headless mode (as used on CI) causes the
|
||||||
|
// `<app-config>` buttons to be in a position that trigger the above issue, we explicitly set the
|
||||||
|
// window size to 1920x1080 when in headless mode.
|
||||||
|
beforeAll(async () => {
|
||||||
|
const config = await browser.getProcessedConfig();
|
||||||
|
if (config.capabilities?.chromeOptions?.args?.includes('--headless')) {
|
||||||
|
browser.driver.manage().window().setSize(1920, 1080);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
beforeEach(() => browser.get(''));
|
beforeEach(() => browser.get(''));
|
||||||
|
|
||||||
describe('Heroes', () => {
|
describe('Heroes', () => {
|
||||||
|
@ -66,6 +86,7 @@ describe('Http Tests', () => {
|
||||||
await checkLogForMessage('GET "assets/config.json"');
|
await checkLogForMessage('GET "assets/config.json"');
|
||||||
expect(await page.configSpan.getText()).toContain('Heroes API URL is "api/heroes"');
|
expect(await page.configSpan.getText()).toContain('Heroes API URL is "api/heroes"');
|
||||||
expect(await page.configSpan.getText()).toContain('Textfile URL is "assets/textfile.txt"');
|
expect(await page.configSpan.getText()).toContain('Textfile URL is "assets/textfile.txt"');
|
||||||
|
expect(await page.configSpan.getText()).toContain('Date is "Wed Jan 29 2020" (date)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can fetch the configuration JSON file with headers', async () => {
|
it('can fetch the configuration JSON file with headers', async () => {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<span *ngIf="config">
|
<span *ngIf="config">
|
||||||
<p>Heroes API URL is "{{config.heroesUrl}}"</p>
|
<p>Heroes API URL is "{{config.heroesUrl}}"</p>
|
||||||
<p>Textfile URL is "{{config.textfile}}"</p>
|
<p>Textfile URL is "{{config.textfile}}"</p>
|
||||||
|
<p>Date is "{{config.date.toDateString()}}" ({{getType(config.date)}})</p>
|
||||||
<div *ngIf="headers">
|
<div *ngIf="headers">
|
||||||
Response headers:
|
Response headers:
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
// #docregion
|
// #docregion
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { Config, ConfigService } from './config.service';
|
import { Config, ConfigService } from './config.service';
|
||||||
import { MessageService } from '../message.service';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-config',
|
selector: 'app-config',
|
||||||
|
@ -25,7 +24,7 @@ export class ConfigComponent {
|
||||||
this.headers = undefined;
|
this.headers = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #docregion v1, v2, v3
|
// #docregion v1, v2
|
||||||
showConfig() {
|
showConfig() {
|
||||||
this.configService.getConfig()
|
this.configService.getConfig()
|
||||||
// #enddocregion v1, v2
|
// #enddocregion v1, v2
|
||||||
|
@ -34,25 +33,23 @@ export class ConfigComponent {
|
||||||
error => this.error = error // error path
|
error => this.error = error // error path
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// #enddocregion v3
|
|
||||||
|
|
||||||
showConfig_v1() {
|
showConfig_v1() {
|
||||||
this.configService.getConfig_1()
|
this.configService.getConfig_1()
|
||||||
// #docregion v1, v1_callback
|
// #docregion v1
|
||||||
.subscribe((data: Config) => this.config = {
|
.subscribe((data: Config) => this.config = {
|
||||||
heroesUrl: data.heroesUrl,
|
heroesUrl: data.heroesUrl,
|
||||||
textfile: data.textfile
|
textfile: data.textfile,
|
||||||
|
date: data.date,
|
||||||
});
|
});
|
||||||
// #enddocregion v1_callback
|
|
||||||
}
|
}
|
||||||
// #enddocregion v1
|
// #enddocregion v1
|
||||||
|
|
||||||
showConfig_v2() {
|
showConfig_v2() {
|
||||||
this.configService.getConfig()
|
this.configService.getConfig()
|
||||||
// #docregion v2, v2_callback
|
// #docregion v2
|
||||||
// clone the data object, using its known Config shape
|
// clone the data object, using its known Config shape
|
||||||
.subscribe((data: Config) => this.config = { ...data });
|
.subscribe((data: Config) => this.config = { ...data });
|
||||||
// #enddocregion v2_callback
|
|
||||||
}
|
}
|
||||||
// #enddocregion v2
|
// #enddocregion v2
|
||||||
|
|
||||||
|
@ -74,5 +71,9 @@ export class ConfigComponent {
|
||||||
makeError() {
|
makeError() {
|
||||||
this.configService.makeIntentionalError().subscribe(null, error => this.error = error );
|
this.configService.makeIntentionalError().subscribe(null, error => this.error = error );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getType(val: any): string {
|
||||||
|
return val instanceof Date ? 'date' : Array.isArray(val) ? 'array' : typeof val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
|
@ -14,6 +14,7 @@ import { catchError, retry } from 'rxjs/operators';
|
||||||
export interface Config {
|
export interface Config {
|
||||||
heroesUrl: string;
|
heroesUrl: string;
|
||||||
textfile: string;
|
textfile: string;
|
||||||
|
date: any;
|
||||||
}
|
}
|
||||||
// #enddocregion config-interface
|
// #enddocregion config-interface
|
||||||
// #docregion proto
|
// #docregion proto
|
||||||
|
|
|
@ -57,8 +57,7 @@
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
cursor: hand;
|
font-family: Arial, sans-serif;
|
||||||
font-family: Arial;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<h3>Heroes</h3>
|
<h3>Heroes</h3>
|
||||||
<!-- #docregion add -->
|
|
||||||
<div>
|
<div>
|
||||||
<label>Hero name:
|
<label>Hero name:
|
||||||
<input #heroName />
|
<input #heroName />
|
||||||
|
@ -12,9 +11,7 @@
|
||||||
search
|
search
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- #enddocregion add -->
|
|
||||||
|
|
||||||
<!-- #docregion list -->
|
|
||||||
<ul class="heroes">
|
<ul class="heroes">
|
||||||
<li *ngFor="let hero of heroes">
|
<li *ngFor="let hero of heroes">
|
||||||
<a (click)="edit(hero)">
|
<a (click)="edit(hero)">
|
||||||
|
@ -23,10 +20,7 @@
|
||||||
<input *ngIf="hero===editHero" [(ngModel)]="hero.name"
|
<input *ngIf="hero===editHero" [(ngModel)]="hero.name"
|
||||||
(blur)="update()" (keyup.enter)="update()">
|
(blur)="update()" (keyup.enter)="update()">
|
||||||
</a>
|
</a>
|
||||||
<!-- #docregion delete -->
|
|
||||||
<button class="delete" title="delete hero"
|
<button class="delete" title="delete hero"
|
||||||
(click)="delete(hero)">x</button>
|
(click)="delete(hero)">x</button>
|
||||||
<!-- #enddocregion delete -->
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- #enddocregion list -->
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
// #enddocregion interceptor-providers
|
// #enddocregion interceptor-providers
|
||||||
import { AuthInterceptor } from './auth-interceptor';
|
import { AuthInterceptor } from './auth-interceptor';
|
||||||
import { CachingInterceptor } from './caching-interceptor';
|
import { CachingInterceptor } from './caching-interceptor';
|
||||||
|
import { CustomJsonInterceptor , CustomJsonParser, JsonParser} from './custom-json-interceptor';
|
||||||
import { EnsureHttpsInterceptor } from './ensure-https-interceptor';
|
import { EnsureHttpsInterceptor } from './ensure-https-interceptor';
|
||||||
import { LoggingInterceptor } from './logging-interceptor';
|
import { LoggingInterceptor } from './logging-interceptor';
|
||||||
// #docregion interceptor-providers
|
// #docregion interceptor-providers
|
||||||
|
@ -21,6 +22,10 @@ export const httpInterceptorProviders = [
|
||||||
// #docregion noop-provider
|
// #docregion noop-provider
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: NoopInterceptor, multi: true },
|
{ provide: HTTP_INTERCEPTORS, useClass: NoopInterceptor, multi: true },
|
||||||
// #enddocregion noop-provider, interceptor-providers
|
// #enddocregion noop-provider, interceptor-providers
|
||||||
|
// #docregion custom-json-interceptor
|
||||||
|
{ provide: HTTP_INTERCEPTORS, useClass: CustomJsonInterceptor, multi: true },
|
||||||
|
{ provide: JsonParser, useClass: CustomJsonParser },
|
||||||
|
// #enddocregion custom-json-interceptor
|
||||||
|
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: EnsureHttpsInterceptor, multi: true },
|
{ provide: HTTP_INTERCEPTORS, useClass: EnsureHttpsInterceptor, multi: true },
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: TrimNameInterceptor, multi: true },
|
{ provide: HTTP_INTERCEPTORS, useClass: TrimNameInterceptor, multi: true },
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue