Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit b09a104

Browse files
committed
docs(cb-inheritance): Add a cookbook about inheritance.
1 parent 0b631da commit b09a104

24 files changed

+650
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
'use strict'; // necessary for es6 output in node
2+
3+
import { browser, element, by } from 'protractor';
4+
5+
// gulp run-e2e-tests --filter=cb-inheritance
6+
describe('Inheritance Cookbook', () => {
7+
8+
beforeAll(() => {
9+
browser.get('');
10+
});
11+
12+
describe('Basic Example', () => {
13+
14+
it('shows movie list with removal buttons', () => {
15+
const movies = element(by.tagName('my-movie-list'));
16+
const avengers = movies.element(by.cssContainingText('li', 'Avengers'));
17+
18+
expect(avengers.isPresent()).toBe(true);
19+
avengers.element(by.buttonText('X')).click();
20+
expect(avengers.isPresent()).toBe(false);
21+
});
22+
23+
it('shows album list with genre and removal buttons', () => {
24+
const albums = element(by.tagName('my-album-list'));
25+
const title = albums.element(by.tagName('h2'));
26+
const abbeyRoad = albums.element(by.cssContainingText('li', 'The Beatles: Abbey Road'));
27+
28+
expect(title.getText()).toEqual('Classic Rock Albums');
29+
expect(abbeyRoad.isPresent()).toBe(true);
30+
abbeyRoad.element(by.buttonText('X')).click();
31+
expect(abbeyRoad.isPresent()).toBe(false);
32+
});
33+
34+
});
35+
36+
describe('Class Metadata Example', () => {
37+
38+
it('shows a list of numbers and a list of superpower titles', () => {
39+
const base = element(by.tagName('my-class-metadata-example'));
40+
const superList = base.element(by.tagName('my-list'));
41+
const subList = base.element(by.tagName('my-superpower-list'));
42+
43+
['1', '2', '3'].forEach(itm => {
44+
expect(superList.element(by.cssContainingText('li', itm)).isPresent()).toBe(true);
45+
});
46+
['Flight', 'Shield'].forEach(itm => {
47+
expect(subList.element(by.cssContainingText('li', itm)).isPresent()).toBe(true);
48+
});
49+
});
50+
51+
});
52+
53+
describe('Property, Method, and Constructor Example', () => {
54+
55+
it('has a canvas with an initial size that reacts to window resize', () => {
56+
const base = element(by.tagName('my-property-metadata-example'));
57+
const canvas = base.element(by.tagName('canvas'));
58+
59+
expect(canvas.getAttribute('width')).toBe('300');
60+
expect(canvas.getAttribute('height')).toBe('200');
61+
browser.manage().window().setSize(500, 400);
62+
expect(canvas.getAttribute('width')).not.toBe('300');
63+
expect(canvas.getAttribute('height')).not.toBe('200');
64+
});
65+
66+
});
67+
68+
});

public/docs/_examples/cb-inheritance/ts/example-config.json

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Component } from '@angular/core';
2+
3+
@Component({
4+
selector: 'my-app',
5+
template: `
6+
<h1>Inheritance examples</h1>
7+
8+
<h2>Basic abstract superclass, subclasses with inherited @Input()</h2>
9+
<my-basic-example></my-basic-example>
10+
11+
<h2>Redefining Class Metadata</h2>
12+
<my-class-metadata-example></my-class-metadata-example>
13+
14+
<h2>Property And Method Inheritance, incl. Lifecycle Methods and Constructors</h2>
15+
<my-property-metadata-example></my-property-metadata-example>
16+
`
17+
})
18+
export class AppComponent {
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { BrowserModule } from '@angular/platform-browser';
2+
import { NgModule } from '@angular/core';
3+
4+
import { BasicExampleModule } from './basic/basic-example.module';
5+
import { BasicExampleComponent } from './basic/basic-example.component';
6+
7+
import { ClassMetadataExampleModule } from './class-metadata/class-metadata-example.module';
8+
import { ClassMetadataExampleComponent } from './class-metadata/class-metadata-example.component';
9+
10+
import { PropertyMetadataExampleModule } from './property-metadata/property-metadata-example.module';
11+
import { AppComponent } from './app.component';
12+
13+
@NgModule({
14+
imports: [
15+
BrowserModule,
16+
BasicExampleModule,
17+
ClassMetadataExampleModule,
18+
PropertyMetadataExampleModule
19+
],
20+
declarations: [
21+
AppComponent,
22+
BasicExampleComponent,
23+
ClassMetadataExampleComponent
24+
],
25+
bootstrap: [ AppComponent ]
26+
})
27+
export class AppModule {
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// #docregion
2+
import { Component, Input } from '@angular/core';
3+
import { ListBaseComponent } from './list-base.component';
4+
import { Album } from '../models';
5+
6+
@Component({
7+
selector: 'my-album-list',
8+
template: `
9+
<h2>{{ genre }} Albums</h2>
10+
<ul>
11+
<li *ngFor="let album of list">
12+
{{album.artist}}: {{ album.title }}
13+
<button (click)="remove(album)">X</button>
14+
</li>
15+
</ul>
16+
`
17+
})
18+
export class AlbumListComponent extends ListBaseComponent<Album> {
19+
@Input() genre: string;
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Component } from '@angular/core';
2+
import { Movie, Album } from '../models';
3+
4+
@Component({
5+
selector: 'my-basic-example',
6+
template: `
7+
<h1>Media Library</h1>
8+
<my-movie-list [list]="movies">
9+
</my-movie-list>
10+
<my-album-list [list]="albums" genre="Classic Rock">
11+
</my-album-list>
12+
`
13+
})
14+
export class BasicExampleComponent {
15+
movies: Movie[] = [
16+
{title: 'Avengers'},
17+
{title: 'X-Men'}
18+
];
19+
albums: Album[] = [
20+
{artist: 'Fleetwood Mac', title: 'Rumours'},
21+
{artist: 'The Beatles', title: 'Abbey Road'}
22+
];
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// #docregion
2+
import { NgModule } from '@angular/core';
3+
import { CommonModule } from '@angular/common';
4+
5+
import { AlbumListComponent } from './album-list.component';
6+
import { MovieListComponent } from './movie-list.component';
7+
8+
@NgModule({
9+
imports: [ CommonModule ],
10+
declarations: [ AlbumListComponent, MovieListComponent ],
11+
exports: [ AlbumListComponent, MovieListComponent ]
12+
})
13+
export class BasicExampleModule {
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// #docregion
2+
import { Input } from '@angular/core';
3+
4+
export abstract class ListBaseComponent<T> {
5+
@Input() list: T[];
6+
7+
remove(item: T) {
8+
const index = this.list.indexOf(item);
9+
if (index >= 0) {
10+
this.list.splice(index, 1);
11+
}
12+
}
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// #docregion
2+
import { Component, EventEmitter, Output } from '@angular/core';
3+
import { ListBaseComponent } from './list-base.component';
4+
import { Movie } from '../models';
5+
6+
@Component({
7+
selector: 'my-movie-list',
8+
template: `
9+
<h2>Movies</h2>
10+
<ul>
11+
<li *ngFor="let movie of list">
12+
{{ movie.title }}
13+
<button (click)="remove(movie)">X</button>
14+
</li>
15+
</ul>
16+
`
17+
})
18+
export class MovieListComponent extends ListBaseComponent<Movie> {
19+
@Output() movieRemoved = new EventEmitter();
20+
21+
remove(movie: Movie) {
22+
super.remove(movie);
23+
this.movieRemoved.emit(movie);
24+
}
25+
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Component } from '@angular/core';
2+
import { Superpower } from '../models';
3+
4+
@Component({
5+
selector: 'my-class-metadata-example',
6+
template: `
7+
<h2>Class Metadata Inheritance Example</h2>
8+
9+
<h3>Base Component</h3>
10+
<my-list [list]="numbers"></my-list>
11+
12+
<h3>Child Component</h3>
13+
<my-superpower-list [list]="superpowers"></my-superpower-list>
14+
`
15+
})
16+
export class ClassMetadataExampleComponent {
17+
numbers = [1, 2, 3, 4];
18+
superpowers: Superpower[] = [
19+
{title: 'Flight'},
20+
{title: 'Shield'}
21+
];
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// #docregion
2+
import { NgModule } from '@angular/core';
3+
import { CommonModule } from '@angular/common';
4+
5+
import { ListComponent } from './list.component';
6+
import { SuperpowerListComponent } from './superpower-list.component';
7+
8+
@NgModule({
9+
imports: [ CommonModule ],
10+
declarations: [ ListComponent, SuperpowerListComponent ],
11+
exports: [ ListComponent, SuperpowerListComponent ]
12+
})
13+
export class ClassMetadataExampleModule {
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<ul>
2+
<li *ngFor="let item of list">
3+
{{ itemToString(item) }}
4+
</li>
5+
</ul>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// #docregion
2+
import { Component, Input } from '@angular/core';
3+
4+
@Component({
5+
moduleId: module.id,
6+
selector: 'my-list',
7+
templateUrl: './list.component.html'
8+
})
9+
export class ListComponent {
10+
@Input() list: any[];
11+
12+
itemToString(item: any): string {
13+
return item && item.toString();
14+
}
15+
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// #docregion
2+
import { Component } from '@angular/core';
3+
4+
import { ListComponent } from './list.component';
5+
import { Superpower } from '../models';
6+
7+
@Component({
8+
moduleId: module.id,
9+
selector: 'my-superpower-list',
10+
templateUrl: './list.component.html' // Must redeclare!
11+
})
12+
export class SuperpowerListComponent extends ListComponent {
13+
14+
itemToString(item: Superpower): string {
15+
return item.title;
16+
}
17+
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export interface Movie {
2+
title: string;
3+
}
4+
5+
export interface Album {
6+
title: string;
7+
artist: string;
8+
}
9+
10+
export interface Superpower {
11+
title: string;
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// #docplaster
2+
// #docregion
3+
import { Component, ElementRef, Renderer, ViewChild } from '@angular/core';
4+
5+
import { FullSizeBaseComponent } from './full-size-base.component';
6+
7+
// #docregion di
8+
@Component({
9+
selector: 'my-canvas',
10+
template: '<canvas #canvas></canvas>',
11+
styles: [`canvas { border: 1px solid black; }`]
12+
})
13+
// #docregion viewchild
14+
// #docregion afterviewinit
15+
// #docregion hostlistener
16+
export class CanvasComponent extends FullSizeBaseComponent {
17+
18+
// #enddocregion afterviewinit
19+
// #enddocregion hostlistener
20+
// #enddocregion di
21+
@ViewChild('canvas')
22+
child: ElementRef;
23+
24+
// #enddocregion viewchild
25+
// #docregion di
26+
27+
constructor(renderer: Renderer, private elementRef: ElementRef) {
28+
super(renderer);
29+
}
30+
31+
// #enddocregion di
32+
// #docregion afterviewinit
33+
ngAfterViewInit() {
34+
super.ngAfterViewInit(); // Must call super!
35+
this.draw();
36+
}
37+
38+
// #enddocregion afterviewinit
39+
// #docregion hostlistener
40+
onResize(event: any) {
41+
super.onResize(event);
42+
this.draw();
43+
}
44+
45+
// #enddocregion hostlistener
46+
private draw() {
47+
const ctx: CanvasRenderingContext2D = this.child.nativeElement.getContext('2d');
48+
ctx.fillRect(10, 10, 100, 100);
49+
}
50+
// #docregion viewchild
51+
// #docregion afterviewinit
52+
// #docregion hostlistener
53+
// #docregion di
54+
}
55+
// #enddocregion viewchild
56+
// #enddocregion afterviewinit
57+
// #enddocregion hostlistener
58+
// #enddocregion di

0 commit comments

Comments
 (0)