diff --git a/public/docs/_examples/intro/ts/.gitignore b/public/docs/_examples/intro/ts/.gitignore new file mode 100644 index 0000000000..6724ce3596 --- /dev/null +++ b/public/docs/_examples/intro/ts/.gitignore @@ -0,0 +1 @@ +src/**/*.js \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/package.json b/public/docs/_examples/intro/ts/package.json new file mode 100644 index 0000000000..b2b21e7953 --- /dev/null +++ b/public/docs/_examples/intro/ts/package.json @@ -0,0 +1,21 @@ +{ + "name": "angular2-template-syntax", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "tsc": "tsc -p src -w", + "start": "live-server --open=src" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "angular2": "2.0.0-alpha.46", + "systemjs": "0.19.2" + }, + "devDependencies": { + "live-server": "^0.8.1", + "typescript": "^1.6.2" + } +} diff --git a/public/docs/_examples/intro/ts/src/app/backend.service.ts b/public/docs/_examples/intro/ts/src/app/backend.service.ts new file mode 100644 index 0000000000..bfc629fc8c --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/backend.service.ts @@ -0,0 +1,21 @@ +import {Injectable} from 'angular2/angular2'; +import {Logger} from './logger.service'; +import {Hero} from './hero'; + +@Injectable() +export class BackendService { + constructor(private _logger: Logger) {} + + getAll(type: {new(...args:any[]): any }) : any[]{ + if (type === Hero) { + // TODO get from the database and return as a promise + return [ + new Hero('Windstorm'), + new Hero('Mr. Nice'), + new Hero('Magneta')]; + } + let err = new Error('Cannot get object of this type'); + this._logger.error(err); + throw err; + } +} \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/app/boot.ts b/public/docs/_examples/intro/ts/src/app/boot.ts new file mode 100644 index 0000000000..23072553c5 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/boot.ts @@ -0,0 +1,11 @@ +import {bootstrap} from 'angular2/angular2'; +import {BackendService} from './backend.service'; +import {HeroService} from './hero.service'; +import {Logger} from './logger.service'; +import {HeroListComponent} from './hero-list.component'; + +// #docregion bootstrap +bootstrap(HeroListComponent, [ + BackendService, HeroService, Logger +]); +// #enddocregion bootstrap diff --git a/public/docs/_examples/intro/ts/src/app/hero-detail.component.html b/public/docs/_examples/intro/ts/src/app/hero-detail.component.html new file mode 100644 index 0000000000..6e32ecaade --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero-detail.component.html @@ -0,0 +1,5 @@ +
+Hero name: + + + \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/app/hero-detail.component.ts b/public/docs/_examples/intro/ts/src/app/hero-detail.component.ts new file mode 100644 index 0000000000..78c94af9a1 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero-detail.component.ts @@ -0,0 +1,11 @@ +import {Component, Input} from 'angular2/angular2'; +import {Hero} from './hero'; + +@Component({ + selector: 'hero-detail', + templateUrl: 'app/hero-detail.component.html', + directives: [HeroDetailComponent] +}) +export class HeroDetailComponent { + @Input() hero:Hero; +} \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/app/hero-list.component.1.html b/public/docs/_examples/intro/ts/src/app/hero-list.component.1.html new file mode 100644 index 0000000000..4c3b47eb45 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero-list.component.1.html @@ -0,0 +1,12 @@ + +
{{hero.name}}
+ +
+ + + diff --git a/public/docs/_examples/intro/ts/src/app/hero-list.component.html b/public/docs/_examples/intro/ts/src/app/hero-list.component.html new file mode 100644 index 0000000000..4c983c5456 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero-list.component.html @@ -0,0 +1,8 @@ + +

Hero List

+ +
+ {{hero.name}} +
+ + diff --git a/public/docs/_examples/intro/ts/src/app/hero-list.component.ts b/public/docs/_examples/intro/ts/src/app/hero-list.component.ts new file mode 100644 index 0000000000..120665b0ec --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero-list.component.ts @@ -0,0 +1,36 @@ +// #docplaster + +import {Component} from 'angular2/angular2'; +import {Hero} from './hero'; +import {HeroDetailComponent} from './hero-detail.component'; +import {HeroService} from './hero.service' + +// #docregion metadata +// #docregion providers +@Component({ +// #enddocregion providers + selector: 'hero-list', + templateUrl: 'app/hero-list.component.html', + directives: [HeroDetailComponent], +// #docregion providers + providers: [HeroService] +}) +// #enddocregion providers +// #enddocregion metadata +/* +// #docregion metadata, providers +export class HeroesComponent { ... } +// #enddocregion metadata, providers +*/ +// #docregion class +export class HeroListComponent { +// #docregion ctor + constructor(service: HeroService) { + this.heroes = service.getHeroes(); + } +// #enddocregion ctor + heroes:Hero[]; + selectedHero:Hero; + selectHero(hero: Hero) { this.selectedHero = hero; } +} +// #enddocregion class diff --git a/public/docs/_examples/intro/ts/src/app/hero.service.ts b/public/docs/_examples/intro/ts/src/app/hero.service.ts new file mode 100644 index 0000000000..4833be8a9b --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero.service.ts @@ -0,0 +1,18 @@ +import {Injectable} from 'angular2/angular2'; +import {Hero} from './hero'; +import {BackendService} from './backend.service'; +import {Logger} from './logger.service'; + +// #docregion class +@Injectable() +export class HeroService { + constructor(private _backend: BackendService, private _logger:Logger){} + + getHeroes() { + // TODO return as a promise + let heroes = this._backend.getAll(Hero); + this._logger.log(`Got ${heroes.length} heroes from the server.`); + return heroes; + } +} +// #enddocregion class \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/app/hero.ts b/public/docs/_examples/intro/ts/src/app/hero.ts new file mode 100644 index 0000000000..4ff4d73792 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/hero.ts @@ -0,0 +1,3 @@ +export class Hero { + constructor(public name:string){} +} diff --git a/public/docs/_examples/intro/ts/src/app/logger.service.ts b/public/docs/_examples/intro/ts/src/app/logger.service.ts new file mode 100644 index 0000000000..2f7935fba0 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/app/logger.service.ts @@ -0,0 +1,8 @@ +import {Injectable} from 'angular2/angular2'; + +@Injectable() +export class Logger { + log(msg: any) { console.log(msg); } + error(msg: any) { console.error(msg); } + warn(msg: any) { console.warn(msg); } +} \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/index.html b/public/docs/_examples/intro/ts/src/index.html new file mode 100644 index 0000000000..07272ac54b --- /dev/null +++ b/public/docs/_examples/intro/ts/src/index.html @@ -0,0 +1,19 @@ + + + + Intro to Angular 2 + + + + + + + Loading... + + + \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/plnkr.config b/public/docs/_examples/intro/ts/src/plnkr.config new file mode 100644 index 0000000000..ee199ba476 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/plnkr.config @@ -0,0 +1,8 @@ +{ + "description": "Intro to Angular2", + "files":[ + "!**/*.d.ts", + "!**/*.js", + "!app/hero-list.component.1.*" + ] +} \ No newline at end of file diff --git a/public/docs/_examples/intro/ts/src/tsconfig.json b/public/docs/_examples/intro/ts/src/tsconfig.json new file mode 100644 index 0000000000..48fc224e99 --- /dev/null +++ b/public/docs/_examples/intro/ts/src/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs", + "sourceMap": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "removeComments": false, + "noImplicitAny": true, + "suppressImplicitAnyIndexErrors": true + } +} \ No newline at end of file diff --git a/public/docs/ts/latest/guide/displaying-data.jade b/public/docs/ts/latest/guide/displaying-data.jade index b2f4a2f624..70ac8696fe 100644 --- a/public/docs/ts/latest/guide/displaying-data.jade +++ b/public/docs/ts/latest/guide/displaying-data.jade @@ -16,12 +16,13 @@ include ../../../../_includes/_util-fns figure.image-display img(src="/resources/images/devguide/displaying-data/final.png" alt="Final UI") + .l-main-section :marked ## Showing component properties with interpolation The easiest way to display a component property is to bind the property name through interpolation. - With interpolation, we put the property name in the view template enclosed in double curly braces: { { myHero } } . + With interpolation, we put the property name in the view template, enclosed in double curly braces: {‌{myHero}} . Let's build a small illustrative example together. @@ -95,6 +96,7 @@ figure.image-display We'll adopt the more terse "variable assignment" style in this chapter simply because there will be less code to read. + .l-main-section :marked ## Showing an array property with NgFor @@ -208,6 +210,7 @@ figure.image-display :marked Our display looks the same but we know how much better it is under the hood. + .l-main-section :marked ## Conditional display with NgIf diff --git a/public/docs/ts/latest/guide/index.jade b/public/docs/ts/latest/guide/index.jade index cbcf5addb2..fb8b1ae3b7 100644 --- a/public/docs/ts/latest/guide/index.jade +++ b/public/docs/ts/latest/guide/index.jade @@ -1,10 +1,520 @@ -- var number = 1; -ul.is-plain - for page, slug in public.docs[current.path[1]][current.path[2]].guide._data +include ../../../../_includes/_util-fns - if slug != '_listtype' && slug != 'index' - - var url = "/docs/" + current.path[1] + "/" + current.path[2] + "/" + current.path[3] + "/" + slug + ".html" - - var num = number++ +:marked + The Developers Guide is a practical guide to Angular for experienced programmers who + are building client applications in HTML and JavaScript. +figure + img(src="/resources/images/devguide/intro/people.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) +:marked + We are on a journey together to understand how Angular works and, more importantly, + how to make it work for us. We look at our application requirements and we see problems to solve. +
+ + * How do we get data onto the screen and handle user interactions? + * How do we organize our code into manageable, cohesive chunks of functionality that work together? + * What are the essential Angular building blocks and how do they help? + * How do we minimize routine, mechanical coding in favor of declarative, higher level constructs without losing control? + + This chapter is an introduction in two parts. + 1. [How to read this guide](#how-to-read) + 2. [An Angular architectural overview](#architecture) - li - != partial("../../../../_includes/_hover-card", { icon: "icon-number", number: num, name: page.title, url: url }) +.l-main-section + +:marked + # How to Read this Guide + The chapters of this guide target an Angular feature and how to use it to solve a programming problem. + + Every chapter includes code snippets ... snippets we can reuse in our own applications. + Typically, these snippets are excerpts from a running sample application that accompanies the chapter. + We can often find a link to a live version of that sample near the top of the chapter ... like this one. + + [Live Example](/docs/_examples/intro/ts/src/plnkr.html) + + This link opens in a browser and runs the sample code supporting this chapter's architecture overview. + We can inspect, modify, save, and download the code. + + A few chapters are written as tutorials and are clearly marked as such. + Most chapters are *not* tutorials and do not explain how to build the accompanying sample. + These chapters highlight key points in code but generally don't include the entire source. + We can get that by way of the live link. + + We don't have to read this guide straight through. + The "[Cheat Sheet](cheatsheet.html)" is a handy map to Angular overall. + A few early chapters are arranged sequentially and best read together to establish a foundation in Angular. + But most chapters stand on their own. We can browse to any of them as our interest or some necessity moves us. + + There is a learning path for those of us who are new to Angular. + + It starts *outside* the guide with the [QuickStart](../quickstart). The QuickStart is the "Hello, World" of Angular 2. + It shows us how to setup the libraries and tools we'll need to write *any* Angular app. + It ends with a "proof of life", a running Angular app. + + The [Tutorial](../tutorial) is our next stop. + It walks us step-by-step from where QuickStart leaves off to a simple data-driven app. Simple, yes, but with + the essential characteristics we'd expect of a professional application: + a sensible project structure, data binding, master/detail, services, dependency injection, navigation, and remote data access. + The final iteration of the "[Tour of Heroes](#toh)" is a positive answer to that most important question: + ***can we build an Angular 2 application that does what we need it to do?*** + + We suggest continuing from the "Tour of Heroes" tutorial to the early core chapters of this Developers Guide in the following order: + 1. [Displaying Data](displaying-data.html) + 1. [User Input](user-input.html) + 1. [Forms](forms.html) + 1. [Dependency Injection](dependency-injection.html) + + We might pause at that point to absorb what we've learned and perhaps experiment on our own before diving into [Template Syntax](template-syntax.html). + That chapter is rather dense. It's also essential reading at some point and + we will return to it frequently as we compose our HTML templates, both for understanding and as a reference. + + Follow your own star from there, wherever it leads. + +.l-main-section + +:marked + # Architecture Overview + Angular 2 is a framework to help us build client applications in HTML and JavaScript. + + The framework consists of several cooperating libraries, some of them core and some optional. + + We write applications by composing HTML templates with Angularized-markup, + writing "Component" classes to manage those templates, adding application logic in services, + and handing the top root component to Angular's bootstrapper. + + Angular takes over, presenting our application content in a browser and responding to user interactions + according to the instructions we provided. + +figure + img(src="/resources/images/devguide/intro/airplane.png" alt="Us" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) +:marked + Of course there is more to it than this. + We're cruising at high altitude in this chapter. + We're looking for landmarks. We should expect the details to be fuzzy and obscured by occasional clouds. + + An Angular 2 application rests on seven main building blocks: + 1. [Component](#component) + 1. [Template](#template) + 1. [Metadata](#metadata) + 1. [Data Binding](#data-binding) + 1. [Directive](#directive) + 1. [Service](#service) + 1. [Dependency Injection](#dependency-injection) + +figure + img(src="/resources/images/devguide/intro/overview.png" alt="overview" style="margin-left:-40px;" ) +:marked + Learn these seven and we're on our way. + +.l-main-section + +:marked + ## The Component +figure + img(src="/resources/images/devguide/intro/hero-component.png" alt="Component" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) +:marked + A **Component** controls a patch of screen real estate that we could call a "view". + The shell at the application root with navigation links, that list of heroes, the hero editor ... + they're all views controlled by Components. + + We define a Component's "application logic" - what it does to support the view - inside a class. + The class interacts with the view through an API of properties and methods. + + + A `HeroListComponent`, for example, might have a `heroes` property that returns an array of heroes + that it acquired from a service. + It might have a `selectHero()` method that sets a `selectedHero` property when the user click on a hero from that list. + It might be a class like this: + ++makeExample('intro/ts/src/app/hero-list.component.ts', 'class') +:marked + Angular creates, updates, and destroys components as the user moves through the application. + The developer can take action at each moment in this lifecycle through optional [Lifecycle Hooks](#). +.l-sub-section + :marked + Our example shows the service arriving via the class constructor. + Who calls that constructor? Who provides the service? + For the moment, have faith that Angular is going to deliver an + appropriate `HeroService` when we need it. + +.l-main-section + +:marked + ## The Template +figure + img(src="/resources/images/devguide/intro/template.png" alt="Template" align="left" style="width:200px; margin-left:-40px;margin-right:10px" ) +:marked + We define a Component's view with its companion **Template**. A template is a form of HTML + that tells Angular how to render the Component. + + A template looks like regular HTML much of the time ... and then it gets a bit strange. Here is a + template for our `HeroList` Component ++makeExample('intro/ts/src/app/hero-list.component.html') +:marked + We recognize `

` and `
`. + But there's other markup that no one told us about in school. + What is`*ng-for`, {‌{hero.name}}, `(click)`, `[hero]`, and ``? + These are examples of Angular's [template syntax](template-syntax.html). + We will grow accustomed to that syntax and may even learn to love it. + We'll begin to explain it in a moment. + + Before we do, focus attention on the last line. + The `` tag is a custom element representing the `HeroDetailComponent`. + + The `HeroDetailComponent` is a *different* component than the `HeroListComponent` we've been reviewing. + The `HeroDetailComponent` (code not shown) presents facts about a particular hero, the + hero that the user selects from the list presented by the the `HeroListComponent`. + The `HeroDetailComponent` is a **child** of the the `HeroListComponent`. + +figure + img(src="/resources/images/devguide/intro/component-tree.png" alt="Metadata" align="left" style="width:300px; margin-left:-40px;margin-right:10px" ) +:marked + Notice how `` rests comfortably among the HTML elements we already know. + We can mix ... and will mix ... our custom components with native HTML in the same layouts. + + And in this manner we can and will compose complex component trees to build out our richly featured application. +
+ +.l-main-section + +:marked + ## Angular Metadata +figure + img(src="/resources/images/devguide/intro/metadata.png" alt="Metadata" align="left" style="width:150px; margin-left:-40px;margin-right:10px" ) +:marked +

Metadata tells Angular how to process a class.

+
+:marked + [Looking back](#component-code) at the `HeroListComponent`, we see that it's just a class. + There is no evidence of a framework, no "Angular" in it at all. + + In fact, it really is *just a class*. It's not a component until we *tell Angular about it*. + + We tell Angular that `HeroListComponent` is a component by attaching **metadata** to the class. + + The easy way to attach metadata in TypeScript is with a **decorator**. + Here's some metadata for `HeroListComponent`: ++makeExample('intro/ts/src/app/hero-list.component.ts', 'metadata') +:marked + Here we see the `@Component` decorator which (no surprise) identifies the class + immediately below it as a Component class. + + A decorator is a function. Decorators often have a configuration parameter. + The `@Component` decorator takes a required configuration object with the + information Angular needs to create and present the component and its view. + + Here we see a few of the possible `@Component` configuration options: + + * `selector` - a css selector that tells Angular to create and insert an instance of this component + where it finds a `` tag in *parent* HTML. + If the template of the application shell (a Component) contained +
+code-example(language="html"). + <hero-list></hero-list> +
+:marked + >Angular inserts an instance of the `HeroListComponent` view between those tags. + + * `templateUrl` - the address of this component's template which we showed [above](#the-template). + + * `directives` - an array of the Components or Directives that *this* template requires. + We saw in the last line of our template that we expect Angular to insert a `HeroDetailComponent` + in the space indicated by `` tags. + Angular will do so only if we mention the `HeroDetailComponent` in this `directives` array. + + * `providers` - an array of **dependency injection providers** for services that the component requires. + This is one way to tell Angular that our component's constructor requires a `HeroService` + so it can get the list of heroes to display. We'll get to dependency injection in a moment. +figure + img(src="/resources/images/devguide/intro/template-metadata-component.png" alt="Metadata" align="left" style="height:200px; margin-left:-40px;margin-right:10px" ) +:marked + The `@Component` function takes the configuration object and turns it into metadata that it attaches + to the component class definition. Angular discovers this metadata at runtime and thus knows how to do "the right thing". + + The template, metadata, and component together describe the view. + + We apply other metadata decorators in a similar fashion to guide Angular behavior. + The `@Injectable`, `@Input`, `@Output`, `@RouterConfig` are a few of the more popular decorators + we'll master as our Angular knowledge grows. +
+:marked + The architectural take-away is that we must add metadata to our code + so that Angular knows what to do. + +.l-main-section + +:marked + ## Data Binding + Without a framework, we would be responsible for pushing data values into the HTML controls and turning user responses + into actions and value updates. Writing such push/pull logic by hand is tedious, error-prone and a nightmare to + read as the experienced jQuery programmer can attest +figure + img(src="/resources/images/devguide/intro/databinding.png" alt="Data Binding" style="width:200px; float:left; margin-left:-40px;margin-right:10px" ) +:marked + Angular supports **data binding**, + a mechanism for coordinating parts of a template with parts of a component. + We add binding markup to the template HTML to tell Angular how to connect both sides. + + There are four forms of data binding syntax. Each form has a direction - to the DOM, from the DOM, or in both directions - + as indicated by the arrows in the diagram. +
+:marked + We saw three forms of data binding in our [example](#template) template: ++makeExample('intro/ts/src/app/hero-list.component.1.html', 'binding')(format=".") +:marked + * The {‌{hero.name}} "[interpolation](displaying-data.html#interpolation)" + displays the component's `hero.name` property value within the `
` tags. + + * The `[hero]` [property binding](template-syntax.html#property-binding) passes the `selectedHero` from + the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`. + + * The `(click)` [event binding](user-input.html#click) calls the Component's `selectHero` method when the user clicks + on a hero's name + + **Two-way data binding** is an important fourth form + that combines property and event binding in a single notation using the `ng-model` directive. + We didn't have a two-way binding in the `HeroListComponent` template; here's an example from a different template: + ++makeExample('intro/ts/src/app/hero-detail.component.html', 'ng-model')(format=".") +:marked + In two-way binding, a data property value flows to the input box from the component as with property binding. + The user's changes also flow back to the component, resetting the property to the latest value, + as with event binding. + + Angular processes *all* data bindings once per JavaScript event cycle, + depth-first from the root of the application component tree. +figure + img(src="/resources/images/devguide/intro/component-databinding.png" alt="Data Binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) +:marked + We don't know all the details yet + but it's clear from these examples that data binding plays an important role in communication + between a template and its component ... +
+figure + img(src="/resources/images/devguide/intro/parent-child-binding.png" alt="Parent/Child binding" style="float:left; width:300px; margin-left:-40px;margin-right:10px" ) +:marked + ... ***and*** between parent and child components +
+ +.l-main-section + +:marked + ## The Directive +figure + img(src="/resources/images/devguide/intro/directive.png" alt="Parent child" style="float:left; width:150px; margin-left:-40px;margin-right:10px" ) +:marked + Our Angular templates are *dynamic*. When Angular renders them, it transforms the DOM + according to the instructions given by a **Directive**. + + A directive is a class with directive metadata. In TypeScript we'd apply the `@Directive` decorator + to attach metadata to the class. +
+:marked + We already met one form of directive: the component. A component is a *directive-with-a-template* + and the `@Component` decorator is actually a `@Directive` decorator extended with template-oriented features. + +.l-sub-section + :marked + While the **component is technically a directive**, + it is so distictive and central to Angular applications that we chose + to separate the component from the directive in our architectural overview. +:marked + There are two *other* kinds of directives as well that we call "structural" and "attribute" directives. + + They tend to appear within an element tag like attributes, + sometimes by name but more often as the target of an assignment or a binding. + + **Structural** directives alter layout by adding, removing, and replacing elements in DOM. + + We see two built-in structural directives at play in our [example](#template) template: ++makeExample('intro/ts/src/app/hero-list.component.1.html', 'structural')(format=".") +:marked + * [`*ng-for`](displaying-data.html#ng-for) tells Angular to stamp out one `
` per hero in the `heroes` list. + * [`*ng-if`](displaying-data.html#ng-if) includes the `HeroDetail` component only if a selected hero exists. + + **Attribute** directives alter the appearance or behavior of an existing element. + In templates they look like regular HTML attributes, hence the name. + + The `ng-model` directive, which implements two-way data binding, is an example of an attribute directive. ++makeExample('intro/ts/src/app/hero-detail.component.html', 'ng-model')(format=".") +:marked + It modifies the behavior of an existing element (typically an ``) + by setting its display value property and responding to change events. + + Angular ships with a small number of other directives that either alter the layout structure + (e.g. [ng-switch](template-syntax.html#ng-switch)) + or modify aspects of DOM elements and components + (e.g. [ng-style](template-syntax.html#ng-style) and [ng-class](template-syntax.html#ng-class)). + + And of course we can write our own directives. + +.l-main-section + +:marked + ## The Service +figure + img(src="/resources/images/devguide/intro/service.png" alt="Service" style="float:left; margin-left:-40px;margin-right:10px" ) +:marked + "Service" is a broad category encompassing any value, function or feature that our application needs. + + Almost anything can be a service. + A service is typically a class with a narrow, well-defined purpose. It should do something specific and do it well. +
+:marked + Examples include: + * logging service + * data service + * message bus + * tax calculator + * application configuration + + There is nothing specifically "Angular" about services. Angular itself has no definition of a "service". + There is no service base class, no place to register a "service". + + Yet services are fundamental to any Angular application. Our components are big consumers of service. + + We prefer our component classes lean. Our components don't fetch data from the server, + they don't validate user input, they don't log directly to console. They delegate such task to services. + + A component's job is to enable the user experience and nothing more. It mediates between the view (rendered by the template) + and the application logic (which often includes some notion of a "model"). + A good component presents properties and methods for data binding. + It delegates everything non-trivial to services. + + Angular doesn't *enforce* these principles. + It won't complain if write a "kitchen sink" component with 3000 lines. + + Angular does help us *follow* these principles ... by making it easy to factor our + application logic into services and make those services available to components through *dependency injection*. + +.l-main-section + +:marked + ## Dependency Injection +figure + img(src="/resources/images/devguide/intro/dependency-injection.png" alt="Service" style="float:left; width:200px; margin-left:-40px;margin-right:10px" ) +:marked + "Dependency Injection" is a way to supply a new instance of a class + with the fully-formed dependencies it requires. Most dependencies are services. + Angular uses dependency injection to provide new components with the services they need. +
+:marked + In TypeScript, Angular can tell which services a component needs by looking at the types of its constructor parameters. + For example, the constructor of our `HeroListComponent` needs the `HeroService`: ++makeExample('intro/ts/src/app/hero-list.component.ts', 'ctor') +:marked + When Angular creates a component, it first asks an **Injector** for + the services that the component requires. + + An `Injector` maintains a container of service instances that it has previously created. + If a requested service instance is not in the container, the injector makes one and adds it to the container + before returning the service to Angular. + When all requested services have been resolved and returned, + Angular can call the component's constructor with those services as arguments. + This is what we mean by *dependency injection*. + + The process of `HeroService` injection looks a bit like this: +figure + img(src="/resources/images/devguide/intro/injector-injects.png" alt="Service" ) +:marked + If the `Injector` doesn't have a `HeroService`, how does it know how to make one? + + In brief, we must have previously registered a **provider** of the `HeroService` with the `Injector`. + A provider is something that can create or return a service, typically the service class itself. + + We can register providers at any level of the application component tree. + We often do so at the root when we bootstrap the application so that + the same instance of a service is available everywhere. ++makeExample('intro/ts/src/app/boot.ts', 'bootstrap') +:marked + Alternatively, we might register at a component level ... ++makeExample('intro/ts/src/app/hero-list.component.ts', 'providers') +:marked + ... in which case we get a new instance of the + service with each new instance of that component. + + We've vastly over-simplified dependency injection for this overview. + We can learn the full story in the [Dependency Injection](dependency-injection.html) chapter. + + The points to remember are: + * dependency injection is wired into the framework and used everywhere.

+ * the `Injector` is the main mechanism. + * an injector maintains a *container* of service instances that it created. + * an injector can create a new service instance from a *provider*. + * a *provider* is a recipe for creating a service. + + * we register *providers* with injectors. + + +.l-main-section +:marked + # The Other Stuff + + We've learned just a bit about the seven main building blocks of an Angular application + 1. [Component](#component) + 1. [Template](#template) + 1. [Metadata](#metadata) + 1. [Data Binding](#data-binding) + 1. [Directive](#directive) + 1. [Service](#service) + 1. [Dependency Injection](#dependency-injection) + + That's a foundation for everything else in an Angular application + and it's more than enough to get going. + But it doesn't include everything we'll need or want to know. + + Below is a brief, alphabetical list of other important Angular features and services. + Most of them are covered in this Developers Guide (or soon will be): + + >**Animations** - A forthcoming animation library makes it easy for developers to animate component behavior + without deep knowledge of animation techniques or css. + + >**Bootstrap** - A method to configure and launch the root application component. + + >**Change Detection** - Learn how Angular decides that a component property value has changed and + when to update the screen. + Learn how it uses **zones** to intercept asynchronous activity and run its change detection strategies. + + >**Component Router** - With the Component Router service, users can navigate a multi-screen application + in a familiar web browsing style using URLs. + + >**Events** - The DOM raise events. So can components and services. Angular offers mechanisms for + publishing and subscribing to events including an implementation of the [RxJS Observable](https://github.com/zenparsing/es-observable) proposal. + + >**[Forms](forms.html)** - Support complex data entry scenarios with HTML-based validation and dirty checking. + + >**HTTP** - Communicate with a server to get data, save data, and invoke server-side actions with this Angular HTTP client. + + >**Lifecycle Hooks** - We can tap into key moments in the lifetime of a component, from its creation to its destruction, + by implementing the "Lifecycle Hook" interfaces. + + >**[Pipes](pipes.html)** - Services that transform values for display. + We can put pipes in our templates to improve the user experience. For example, + this `currency` pipe expression, +
+code-example(language="javascript" linenumbers="."). + price | currency:'USD':true' +
+:marked + >displays a price of "42.33" as `$42.33`. + + >**[Testing](../testing/index.html)** - Angular provides a testing library for "unit testing" our application parts as they + interact with the Angular framework. + + +.l-main-section +:marked + # Appendix: The Hero Staffing Agency + The final phase of the tutorial Tour of Heroes app runs like this. +figure.image-display + img(src='/resources/images/devguide/toh/toh-anim.gif' alt="Tour of Heroes in Action" height="300px") +:marked + There's a backstory to the "Tour of Heroes" and every sample in this guide. + + The world is full of crises large and small. + Fortunately, there are courageous heroes prepared to take on every challenge. + The shadowy "Hero Staffing Agency" matches crises to heroes. + + We are contract developers, hired by The Agency to build an application to manage their operations. + The Agency maintains a stable of heroes with special powers. + We ordinary humans submit our crises as job requests. The heroes bid to take the job and The Agency + assigns each job accordingly. Our application handles every detail of recruiting, tracking and job assignment. diff --git a/public/docs/ts/latest/guide/user-input.jade b/public/docs/ts/latest/guide/user-input.jade index 1594c23305..48694255a6 100644 --- a/public/docs/ts/latest/guide/user-input.jade +++ b/public/docs/ts/latest/guide/user-input.jade @@ -15,6 +15,7 @@ include ../../../../_includes/_util-fns A click Event Binding makes for a quick illustration. +makeExample('user-input/ts/src/app/app.html', 'click-me-button')(format=".") + :marked The `(click)` to the left of the equal sign identifies the button's click event as the **target of the binding**. The text within quotes on the right is the "**template expression**" in which we @@ -178,7 +179,7 @@ figure.image-display by importing the `CORE_DIRECTIVES` constant and adding it to the @Component decorator's `directives` array. - We learned about `NgFor` in the "[Displaying Data](./displaying-data.html)" chapter. + We learned about `NgFor` in the "[Displaying Data](displaying-data.html#ng-for)" chapter. .l-main-section diff --git a/public/resources/images/devguide/intro/airplane.png b/public/resources/images/devguide/intro/airplane.png new file mode 100644 index 0000000000..30a3e36a1c Binary files /dev/null and b/public/resources/images/devguide/intro/airplane.png differ diff --git a/public/resources/images/devguide/intro/component-databinding.png b/public/resources/images/devguide/intro/component-databinding.png new file mode 100644 index 0000000000..6128a39080 Binary files /dev/null and b/public/resources/images/devguide/intro/component-databinding.png differ diff --git a/public/resources/images/devguide/intro/component-tree.png b/public/resources/images/devguide/intro/component-tree.png new file mode 100644 index 0000000000..19b0a165d9 Binary files /dev/null and b/public/resources/images/devguide/intro/component-tree.png differ diff --git a/public/resources/images/devguide/intro/databinding.png b/public/resources/images/devguide/intro/databinding.png new file mode 100644 index 0000000000..a0fb296b2f Binary files /dev/null and b/public/resources/images/devguide/intro/databinding.png differ diff --git a/public/resources/images/devguide/intro/dependency-injection.png b/public/resources/images/devguide/intro/dependency-injection.png new file mode 100644 index 0000000000..4a890137e9 Binary files /dev/null and b/public/resources/images/devguide/intro/dependency-injection.png differ diff --git a/public/resources/images/devguide/intro/directive.png b/public/resources/images/devguide/intro/directive.png new file mode 100644 index 0000000000..48efa56b16 Binary files /dev/null and b/public/resources/images/devguide/intro/directive.png differ diff --git a/public/resources/images/devguide/intro/hero-component.png b/public/resources/images/devguide/intro/hero-component.png new file mode 100644 index 0000000000..46ce4ba476 Binary files /dev/null and b/public/resources/images/devguide/intro/hero-component.png differ diff --git a/public/resources/images/devguide/intro/injector-injects.png b/public/resources/images/devguide/intro/injector-injects.png new file mode 100644 index 0000000000..c680bc7b34 Binary files /dev/null and b/public/resources/images/devguide/intro/injector-injects.png differ diff --git a/public/resources/images/devguide/intro/metadata.png b/public/resources/images/devguide/intro/metadata.png new file mode 100644 index 0000000000..4b7b2dc377 Binary files /dev/null and b/public/resources/images/devguide/intro/metadata.png differ diff --git a/public/resources/images/devguide/intro/overview.png b/public/resources/images/devguide/intro/overview.png new file mode 100644 index 0000000000..0c1e0220a1 Binary files /dev/null and b/public/resources/images/devguide/intro/overview.png differ diff --git a/public/resources/images/devguide/intro/parent-child-binding.png b/public/resources/images/devguide/intro/parent-child-binding.png new file mode 100644 index 0000000000..b4e5deef68 Binary files /dev/null and b/public/resources/images/devguide/intro/parent-child-binding.png differ diff --git a/public/resources/images/devguide/intro/people.png b/public/resources/images/devguide/intro/people.png new file mode 100644 index 0000000000..626c7a21ed Binary files /dev/null and b/public/resources/images/devguide/intro/people.png differ diff --git a/public/resources/images/devguide/intro/service.png b/public/resources/images/devguide/intro/service.png new file mode 100644 index 0000000000..3b61f892cc Binary files /dev/null and b/public/resources/images/devguide/intro/service.png differ diff --git a/public/resources/images/devguide/intro/template-metadata-component.png b/public/resources/images/devguide/intro/template-metadata-component.png new file mode 100644 index 0000000000..e759f14dea Binary files /dev/null and b/public/resources/images/devguide/intro/template-metadata-component.png differ diff --git a/public/resources/images/devguide/intro/template.png b/public/resources/images/devguide/intro/template.png new file mode 100644 index 0000000000..3d6c0b1bae Binary files /dev/null and b/public/resources/images/devguide/intro/template.png differ