Angular 2: Difference between revisions
revision on headers |
|||
Line 1: | Line 1: | ||
= | = Notes from Quickstart tutorial from the angular site = | ||
=== turn off connection logging | = npm lite-server related = | ||
== turn off connection logging == | |||
Setting logConnection to false in bs-config.json did not work. The connection is logged by a middleware called connect-logger and you can disable it by creating <span class="package">bs-config.js</span> with the following content. | Setting logConnection to false in bs-config.json did not work. The connection is logged by a middleware called connect-logger and you can disable it by creating <span class="package">bs-config.js</span> with the following content. | ||
Line 11: | Line 13: | ||
</source> | </source> | ||
== turn off file change updates == | |||
Add <span class="shell">logFileChanges</span> line to disable logging of file change updates. | Add <span class="shell">logFileChanges</span> line to disable logging of file change updates. | ||
Line 22: | Line 24: | ||
</source> | </source> | ||
= Event = | |||
An example event binding. | An example event binding. | ||
Line 38: | Line 40: | ||
[https://developer.mozilla.org/en-US/docs/Web/Events List of events that can be used on MDN.] | [https://developer.mozilla.org/en-US/docs/Web/Events List of events that can be used on MDN.] | ||
= Data Architecture = | |||
== Observables (aka Reactive Programming) == | |||
* Promises emit single values, and streams emit multiple values | * Promises emit single values, and streams emit multiple values | ||
Line 48: | Line 50: | ||
* streams are composable -- they are like a pipeline of operations over your data | * streams are composable -- they are like a pipeline of operations over your data | ||
== Ways to get data into the application == | |||
* AJAX HTTP Requests | * AJAX HTTP Requests | ||
Line 56: | Line 58: | ||
* Service Workers | * Service Workers | ||
== New ideas on the horizon == | |||
* MVW | * MVW | ||
Line 63: | Line 65: | ||
* Falcor | * Falcor | ||
= Forms = | |||
== FormBuilder == | |||
<syntaxhighlight lang="typescript"> | <syntaxhighlight lang="typescript"> | ||
Line 83: | Line 85: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== @Component Annotation == | |||
<source lang="typescript"> | <source lang="typescript"> | ||
Line 117: | Line 119: | ||
ngForm includes the <code>form</code> tag in its selector (instead of requiring you to explicitly add ngForm as an attribute). If you inject FORM_DIRECTIVES, ngForm will get automatically attached to any <form> tags you have in your view. | ngForm includes the <code>form</code> tag in its selector (instead of requiring you to explicitly add ngForm as an attribute). If you inject FORM_DIRECTIVES, ngForm will get automatically attached to any <form> tags you have in your view. | ||
== ControlGroup == | |||
<syntaxhighlight lang="typescript"> | <syntaxhighlight lang="typescript"> | ||
Line 129: | Line 131: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Control == | |||
<syntaxhighlight lang="typescript"> | <syntaxhighlight lang="typescript"> | ||
Line 143: | Line 145: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
= Built-in Components = | |||
== <nowiki>ngIf</nowiki> == | |||
<syntaxhighlight lang="html"> | <syntaxhighlight lang="html"> | ||
Line 154: | Line 156: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== <nowiki>ngSwitch</nowiki> == | |||
<syntaxhighlight lang="html"> | <syntaxhighlight lang="html"> | ||
Line 164: | Line 166: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== <nowiki>ngStyle</nowiki> == | |||
<syntaxhighlight lang="html"> | <syntaxhighlight lang="html"> | ||
Line 174: | Line 176: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== <nowiki>ngClass</nowiki> == | |||
<syntaxhighlight lang="css"> | <syntaxhighlight lang="css"> | ||
Line 219: | Line 221: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== <nowiki>ngFor</nowiki> == | |||
<syntaxhighlight lang="typescript"> | <syntaxhighlight lang="typescript"> | ||
Line 239: | Line 241: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== <nowiki>ngNonBindable</nowiki> == | |||
<syntaxhighlight lang="html"> | <syntaxhighlight lang="html"> | ||
Line 250: | Line 252: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
= Miscellaneous = | |||
Four basic libraries to include | Four basic libraries to include |
Revision as of 14:13, 30 June 2016
Notes from Quickstart tutorial from the angular site
turn off connection logging
Setting logConnection to false in bs-config.json did not work. The connection is logged by a middleware called connect-logger and you can disable it by creating bs-config.js with the following content.
module.exports = {
server: { middleware: { 0: null }}
};
turn off file change updates
Add logFileChanges line to disable logging of file change updates.
module.exports = {
server: { middleware: { 0: null }},
logFileChanges: false
};
Event
An example event binding.
<button (click)="onSave()">Save</button>
Canonical form:
<button on-click="onSave()">Save</button>
List of events that can be used on MDN.
Data Architecture
Observables (aka Reactive Programming)
- Promises emit single values, and streams emit multiple values
- callbacks -> promises
- code subscribes to be notified of changes and streams "push" data to these subscribers
- RxJS is functional -- functional operators are applied like for arrays
- streams are composable -- they are like a pipeline of operations over your data
Ways to get data into the application
- AJAX HTTP Requests
- Websockets
- Indexdb
- LocalStorage
- Service Workers
New ideas on the horizon
- MVW
- Flux
- Observables
- Falcor
Forms
FormBuilder
export class DemoFormSkuBuilder {
myForm: ControlGroup;
constructor(fb: FormBuilder) {
this.myForm = fb.group({
'sku': ['ABC123']
});
}
onSubmit(value:string): void {
console.log('you submitted value: ',value);
}
}
@Component Annotation
import {Component} from 'angular2/core';
import {FORM_DIRECTIVES} from 'angular2/common';
@Component({
selector: 'demo-form-sku',
directives: [FORM_DIRECTIVES], // a shorthand to several directives for forms
template: `
<div class="ui raised segment">
<h2 class="ui header">Demo Form: Sku</h2>
<form #f="ngForm"
(ngSubmit)="onSubmit(f.value)" // when I submit the form, call onSubmit on my component instance,
// passing the value of the form as the arguments."
classd="ui form">
<div class="field">
<label for="skuInput">SKU</label>
<input type="text"
id="skuInput"
placeholder="SKU"
ngControl="sku">
</div>
<button type="submit class="ui button">Submit</button>
</form>
</div>
`
})
bootstrap(MyApp);
ngForm includes the form
tag in its selector (instead of requiring you to explicitly add ngForm as an attribute). If you inject FORM_DIRECTIVES, ngForm will get automatically attached to any <form> tags you have in your view.
ControlGroup
let personInfo = new ControlGroup({
firstName: new Control("Michael"),
lastName: new Control("Han"),
zip: new Control("90210")
})
// personInfo.value; .errors .dirty .valid
Control
let nameControl = new Control("Test");
let name = nameControl.value;
nameControl.errors; nameControl.dirty; nameControl.valid;
<input type="text" ngControl="name"/>
Built-in Components
ngIf
<div *ngIf="false"></div>
<div *ngIf="a > b"></div>
<div *ngIf="str == 'yes'"></div>
<div *ngIf="myFunc()"></div>
ngSwitch
<div class="container" [ngSwitch]="myVar">
<div *ngSwitchWhen="'A'">Var is A</div>
<div *ngSwitchWhen="'B'">Var is B</div>
<div *ngSwitchDefault>Var is something else</div>
</div>
ngStyle
<div [style.background-color]="'yellow'">Testing</div>
<div [ngStyle]="{color: 'white', 'background-color': 'blue'}">testing</div>
<span [ngStyle]="{color: 'red'}" [style.font-size.px]="fontSize">red text</span>
ngClass
.bordered {
border: 1px dashed black;
background-color: #eee;
}
<div [ngClass]="{borderd: false}">This is never bordered</div>
<div [ngClass]="{borderd: true}">This is always bordered</div>
<div [ngClass]="{borderd: isBordered}">Using object literal. Border {{ isBordered ? "ON":"OFF" }}</div>
toggleBorder() {
this.isBordered = !this.isBordered;
this.classesObj = {
bordered: this.isBordered
};
}
<div [ngClass]="classesObj">Using object var. Border {{classesObj.bordered ? "ON":"OFF"}}</div>
<div class="base" [ngClass]="['blue','round']">This will always have a blue and round classes</div>
this.classList = ['blue','round'];
<div class="base" [ngClass]="classList"
ngFor
this.cities = ['Miami','Sao Paulo','New York'];
<div class="ui list" *ngFor="#c of cities">
<div class="item">{{c}}</div>
</div>
adding index
<div class="ui list" *ngFor="#c of cities; #num = index">
<div class="item">{{num+1}} - {{c}}</div>
</div>
ngNonBindable
<div>
<span class="bordered">{{content}}</span>
<span class="pre" ngNonBindable>
← This is what {{content}} rendered
</span>
</div>
Miscellaneous
Four basic libraries to include
- es6-shim (for older browsers -- standardizes behaviors across browsers)
- angular2-polyfills (for standardizations, especially with zones, promises, and reflection)
- SystemJS (module loader)
- RxJS (enables reactive programming -- tools for Observables)
<script src="node_modules/es6-shim/es6-shim.js"></script>
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<!-- main AngularJS 2 library -->
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
TypeScript app.ts. import {bootstrap}, and {bootstrap} is called destructuring.
/// <reference path="node_modules/anguar2/ts/typings/node/node.d.ts"/>
/// <reference path="node_modules/anguar2/typings/browser.d.ts"/>
import {bootstrap} from "angular2/platform/browser";
import {Component} from "angular2/core";
@Component({
selector: 'hello-world',
template: `
<div>
Hello world
</div>
`
})
class HelloWorld {
}
bootstrap(HelloWorld);
Adding a variable. Adding a property is new to ES5: "name: string;". Double brackets {{ are called "template-tags" (or "mustache tags"). Inside template-tags is expression.
/// <reference path="node_modules/anguar2/ts/typings/node/node.d.ts"/>
/// <reference path="node_modules/anguar2/typings/browser.d.ts"/>
import {bootstrap} from "angular2/platform/browser";
import {Component} from "angular2/core";
@Component({
selector: 'hello-world',
template: `<div>Hello, {{name}}</div>`
})
class HelloWorld {
name: string;
constructor() {
this.name = 'Felipe';
}
}
bootstrap(HelloWorld);
Array. *ngFor
/// <reference path="node_modules/anguar2/ts/typings/node/node.d.ts"/>
/// <reference path="node_modules/anguar2/typings/browser.d.ts"/>
import {bootstrap} from "angular2/platform/browser";
import {Component} from "angular2/core";
@Component({
selector: 'hello-world',
template: `
<ul>
<li *ngFor="#name of names">Hello {{name}}</li>
</ul>
`
})
class HelloWorld {
names: string[];
constructor() {
this.names = ['Ari', 'Carlos', 'Felipe', 'Nate'];
}
}
bootstrap(HelloWorld);
adding interaction.
/// <reference path="node_modules/anguar2/ts/typings/node/node.d.ts"/>
/// <reference path="node_modules/anguar2/typings/browser.d.ts"/>
import {bootstrap} from "angular2/platform/browser";
import {Component} from "angular2/core";
@Component({
selector: 'trainer',
template: `
<form class="ui large form segment">
<h3 class="ui header">Add a Resource</h3>
<div class="field">
<label for="title">Title:</label>
<input type="text" name="title" #newtitle>
</div>
<div class="field">
<label for="link">Link:</label>
<input type="url" name="link" #newlink>
</div>
<div class="field">
<label for="credit">Credit:</label>
<input type="number" name="credit" #newcredit>
</div>
<button (click)="addArticle(newtitle,newlink)" class="ui positive right floated button">Submit resource</button>
</form>
`
})
class TrainerApp {
constructor() {
}
addResource(title: HTMLInputElement, link: HTMLInputElement): void {
console.log(`Adding article title: ${title.value} and link: ${link.value}`);
}
}
bootstrap(TrainerApp);
<input name="title" #newtitle>
Tells Angular to bind this <input> to the variable newtitle. #newtitle syntax is called a resolve.
Storing multiple items.
/// <reference path="node_modules/angular2/ts/typings/node/node.d.ts"/>
/// <reference path="node_modules/angular2/typings/browser.d.ts"/>
import {bootstrap} from "angular2/platform/browser";
import {Component} from "angular2/core";
class Resource {
category: string;
title: string;
link: string;
credit: number;
votes: number;
constructor(title: string, category: string, link: string, credit: number, votes?: number) {
this.category = category;
this.title = title;
this.link = link;
this.credit = credit;
this.votes = votes || 0;
}
voteUp(): void {
this.votes += 1;
}
voteDown(): void {
this.votes -= 1;
}
}
@Component({
selector: 'trainer-item',
inputs: ['resource'],
host: {
class: 'row'
},
template: `
<div class="four wide column center aligned votes">
<div class="ui statistic">
<div class="value">{{resource.votes}}</div>
<div class="label"> Points</div>
</div>
</div>
<div class="twelve wide column">
<a class="ui large header" href="{{resource.link}}">{{resource.title}}</a>
<ul class="ui big horizontal list voters">
<li class="item">
<a href (click)="voteUp()"><i class="arrow up icon"></i> upvote</a>
</li>
<li class="item">
<a href (click)="voteDown()"><i class="arrow down icon"></i> downvote</a>
</li>
</ul>
</div>
`
})
class ResourceComponent {
resource: Resource;
voteUp(): boolean {
this.resource.voteUp();
return false;
}
voteDown(): boolean {
this.resource.voteDown();
return false;
}
}
@Component({
selector: 'trainer',
directives: [ResourceComponent],
template: `
<form class="ui large form segment">
<h3 class="ui header">Add a Resource</h3>
<div class="field">
<label for="title">Title:</label>
<input type="text" name="title" #newtitle>
</div>
<div class="field">
<label for="category">Category:</label>
<input type="text" name="category" #newcategory>
</div>
<div class="field">
<label for="link">Link:</label>
<input type="url" name="link" #newlink>
</div>
<div class="field">
<label for="credit">Credit:</label>
<input type="number" name="credit" #newcredit>
</div>
<button (click)="addResource(newtitle,newcategory,newlink,newcredit)" class="ui positive right floated button">Submit resource</button>
</form>
<div class="ui grid posts">
<trainer-item *ngFor="#resource of resources" [resource]="resource"></trainer-item>
</div>
`
})
class TrainerApp {
resources: Resource[];
constructor() {
this.resources = [
new Resource('Chapter 1','Angular 2','http://angular.io',3,10),
new Resource('Chapter 2','Angular 2','http://angular.io',3,10),
new Resource('Chapter 3','Angular 2','http://angular.io',3,10),
];
}
addResource(title: HTMLInputElement, category: HTMLInputElement, link: HTMLInputElement, credit: HTMLInputElement): void {
console.log(`Adding resource -- title: ${title.value}, category: ${category.value}, link: ${link.value}, credit: ${credit.value}`);
}
}
bootstrap(TrainerApp);
Add sorting functionality.
({
`
...
<div class="ui grid posts">
<trainer-item *ngFor="#res_item of sortedResources()" [resource]="res_item"></trainer-item>
</div>
`
})
class TrainerApp {
resources: Resource[];
constructor() {
this.resources = [
new Resource('Chapter 1','Angular 2','http://angular.io','3',10),
new Resource('Chapter 2','Angular 2','http://angular.io','3',10),
new Resource('Chapter 3','Angular 2','http://angular.io','3',10),
];
}
addResource(title: HTMLInputElement, category: HTMLInputElement, link: HTMLInputElement, credit: HTMLInputElement): void {
console.log(`Adding resource -- title: ${title.value}, category: ${category.value}, link: ${link.value}, credit: ${credit.value}`);
this.resources.push(new Resource(title.value,category.value,link.value,credit.value));
title.value = category.value = link.value = credit.value = '';
}
sortedResources(): Resource[] {
return this.resources.sort((a: Resource, b: Resource) => b.credit - a.credit);
}
}
Advantages of TypeScript over ES5:
- types
- classes
- annotations
- imports
- language utilities (e.g. destructuring)
@Component is called a decorator, which adds metadata to the class that follows it.
Using the Template:... syntax is called template binding.
directives specifies other components we want to be able to use in this view. The option takes an array of classes.
[squareBrackets] pass inputs and (parenthesis) handle outputs.