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

docs(cb-inheritance): Add a cookbook about inheritance. #3323

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions public/docs/_examples/cb-inheritance/e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict'; // necessary for es6 output in node

import { browser, element, by } from 'protractor';

// gulp run-e2e-tests --filter=cb-inheritance
describe('Inheritance Cookbook', () => {

beforeAll(() => {
browser.get('');
});

describe('Basic Example', () => {

it('shows movie list with removal buttons', () => {
const movies = element(by.tagName('my-movie-list'));
const avengers = movies.element(by.cssContainingText('li', 'Avengers'));

expect(avengers.isPresent()).toBe(true);
avengers.element(by.buttonText('X')).click();
expect(avengers.isPresent()).toBe(false);
});

it('shows album list with genre and removal buttons', () => {
const albums = element(by.tagName('my-album-list'));
const title = albums.element(by.tagName('h2'));
const abbeyRoad = albums.element(by.cssContainingText('li', 'The Beatles: Abbey Road'));

expect(title.getText()).toEqual('Classic Rock Albums');
expect(abbeyRoad.isPresent()).toBe(true);
abbeyRoad.element(by.buttonText('X')).click();
expect(abbeyRoad.isPresent()).toBe(false);
});

});

describe('Class Metadata Example', () => {

it('shows a list of numbers and a list of superpower titles', () => {
const base = element(by.tagName('my-class-metadata-example'));
const superList = base.element(by.tagName('my-list'));
const subList = base.element(by.tagName('my-superpower-list'));

['1', '2', '3'].forEach(itm => {
expect(superList.element(by.cssContainingText('li', itm)).isPresent()).toBe(true);
});
['Flight', 'Shield'].forEach(itm => {
expect(subList.element(by.cssContainingText('li', itm)).isPresent()).toBe(true);
});
});

});

describe('Property, Method, and Constructor Example', () => {

it('has a canvas with an initial size that reacts to window resize', () => {
const base = element(by.tagName('my-property-metadata-example'));
const canvas = base.element(by.tagName('canvas'));

expect(canvas.getAttribute('width')).toBe('300');
expect(canvas.getAttribute('height')).toBe('200');
browser.manage().window().setSize(500, 400);
expect(canvas.getAttribute('width')).not.toBe('300');
expect(canvas.getAttribute('height')).not.toBe('200');
});

});

});
19 changes: 19 additions & 0 deletions public/docs/_examples/cb-inheritance/ts/src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Component } from '@angular/core';

@Component({
selector: 'my-app',
template: `
<h1>Inheritance examples</h1>

<h2>Basic abstract superclass, subclasses with inherited @Input()</h2>
<my-basic-example></my-basic-example>

<h2>Redefining Class Metadata</h2>
<my-class-metadata-example></my-class-metadata-example>

<h2>Property And Method Inheritance, incl. Lifecycle Methods and Constructors</h2>
<my-property-metadata-example></my-property-metadata-example>
`
})
export class AppComponent {
}
28 changes: 28 additions & 0 deletions public/docs/_examples/cb-inheritance/ts/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { BasicExampleModule } from './basic/basic-example.module';
import { BasicExampleComponent } from './basic/basic-example.component';

import { ClassMetadataExampleModule } from './class-metadata/class-metadata-example.module';
import { ClassMetadataExampleComponent } from './class-metadata/class-metadata-example.component';

import { PropertyMetadataExampleModule } from './property-metadata/property-metadata-example.module';
import { AppComponent } from './app.component';

@NgModule({
imports: [
BrowserModule,
BasicExampleModule,
ClassMetadataExampleModule,
PropertyMetadataExampleModule
],
declarations: [
AppComponent,
BasicExampleComponent,
ClassMetadataExampleComponent
],
bootstrap: [ AppComponent ]
})
export class AppModule {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// #docregion
import { Component, Input } from '@angular/core';
import { ListBaseComponent } from './list-base.component';
import { Album } from '../models';

@Component({
selector: 'my-album-list',
template: `
<h2>{{ genre }} Albums</h2>
<ul>
<li *ngFor="let album of list">
{{album.artist}}: {{ album.title }}
<button (click)="remove(album)">X</button>
</li>
</ul>
`
})
export class AlbumListComponent extends ListBaseComponent<Album> {
@Input() genre: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Component } from '@angular/core';
import { Movie, Album } from '../models';

@Component({
selector: 'my-basic-example',
template: `
<h1>Media Library</h1>
<my-movie-list [list]="movies">
</my-movie-list>
<my-album-list [list]="albums" genre="Classic Rock">
</my-album-list>
`
})
export class BasicExampleComponent {
movies: Movie[] = [
{title: 'Avengers'},
{title: 'X-Men'}
];
albums: Album[] = [
{artist: 'Fleetwood Mac', title: 'Rumours'},
{artist: 'The Beatles', title: 'Abbey Road'}
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// #docregion
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { AlbumListComponent } from './album-list.component';
import { MovieListComponent } from './movie-list.component';

@NgModule({
imports: [ CommonModule ],
declarations: [ AlbumListComponent, MovieListComponent ],
exports: [ AlbumListComponent, MovieListComponent ]
})
export class BasicExampleModule {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// #docregion
import { Input } from '@angular/core';

export abstract class ListBaseComponent<T> {
@Input() list: T[];

remove(item: T) {
const index = this.list.indexOf(item);
if (index >= 0) {
this.list.splice(index, 1);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// #docregion
import { Component, EventEmitter, Output } from '@angular/core';
import { ListBaseComponent } from './list-base.component';
import { Movie } from '../models';

@Component({
selector: 'my-movie-list',
template: `
<h2>Movies</h2>
<ul>
<li *ngFor="let movie of list">
{{ movie.title }}
<button (click)="remove(movie)">X</button>
</li>
</ul>
`
})
export class MovieListComponent extends ListBaseComponent<Movie> {
@Output() movieRemoved = new EventEmitter();

remove(movie: Movie) {
super.remove(movie);
this.movieRemoved.emit(movie);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component } from '@angular/core';
import { Superpower } from '../models';

@Component({
selector: 'my-class-metadata-example',
template: `
<h2>Class Metadata Inheritance Example</h2>

<h3>Base Component</h3>
<my-list [list]="numbers"></my-list>

<h3>Child Component</h3>
<my-superpower-list [list]="superpowers"></my-superpower-list>
`
})
export class ClassMetadataExampleComponent {
numbers = [1, 2, 3, 4];
superpowers: Superpower[] = [
{title: 'Flight'},
{title: 'Shield'}
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// #docregion
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { ListComponent } from './list.component';
import { SuperpowerListComponent } from './superpower-list.component';

@NgModule({
imports: [ CommonModule ],
declarations: [ ListComponent, SuperpowerListComponent ],
exports: [ ListComponent, SuperpowerListComponent ]
})
export class ClassMetadataExampleModule {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<ul>
<li *ngFor="let item of list">
{{ itemToString(item) }}
</li>
</ul>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// #docregion
import { Component, Input } from '@angular/core';

@Component({
moduleId: module.id,
selector: 'my-list',
templateUrl: './list.component.html'
})
export class ListComponent {
@Input() list: any[];

itemToString(item: any): string {
return item && item.toString();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// #docregion
import { Component } from '@angular/core';

import { ListComponent } from './list.component';
import { Superpower } from '../models';

@Component({
moduleId: module.id,
selector: 'my-superpower-list',
templateUrl: './list.component.html' // Must redeclare!
})
export class SuperpowerListComponent extends ListComponent {

itemToString(item: Superpower): string {
return item.title;
}

}
12 changes: 12 additions & 0 deletions public/docs/_examples/cb-inheritance/ts/src/app/models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export interface Movie {
title: string;
}

export interface Album {
title: string;
artist: string;
}

export interface Superpower {
title: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// #docplaster
// #docregion
import { Component, ElementRef, Renderer, ViewChild } from '@angular/core';

import { FullSizeBaseComponent } from './full-size-base.component';

// #docregion di
@Component({
selector: 'my-canvas',
template: '<canvas #canvas></canvas>',
styles: [`canvas { border: 1px solid black; }`]
})
// #docregion viewchild
// #docregion afterviewinit
// #docregion hostlistener
export class CanvasComponent extends FullSizeBaseComponent {

// #enddocregion afterviewinit
// #enddocregion hostlistener
// #enddocregion di
@ViewChild('canvas')
child: ElementRef;

// #enddocregion viewchild
// #docregion di

constructor(renderer: Renderer, private elementRef: ElementRef) {
super(renderer);
}

// #enddocregion di
// #docregion afterviewinit
ngAfterViewInit() {
super.ngAfterViewInit(); // Must call super!
this.draw();
}

// #enddocregion afterviewinit
// #docregion hostlistener
onResize(event: any) {
super.onResize(event);
this.draw();
}

// #enddocregion hostlistener
private draw() {
const ctx: CanvasRenderingContext2D = this.child.nativeElement.getContext('2d');
ctx.fillRect(10, 10, 100, 100);
}
// #docregion viewchild
// #docregion afterviewinit
// #docregion hostlistener
// #docregion di
}
// #enddocregion viewchild
// #enddocregion afterviewinit
// #enddocregion hostlistener
// #enddocregion di
Loading