QuickStart replaced by Getting Started (TS/JS) versions

This commit is contained in:
Ward Bell 2015-10-14 20:25:19 -07:00
parent 653f41707d
commit 9321c9f0ad
19 changed files with 1515 additions and 1501 deletions

9
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,9 @@
// Place your settings in this file to overwrite default and user settings.
{
// Controls the rendering size of tabs in characters. Accepted values: "auto", 2, 4, 6, etc. If set to "auto", the value will be guessed when a file is opened.
"editor.tabSize": 2,
// Controls if the editor will insert spaces for tabs. Accepted values: "auto", true, false. If set to "auto", the value will be guessed when a file is opened.
"editor.insertSpaces": true,
// When enabled, will trim trailing whitespace when you save a file.
"files.trimTrailingWhitespace": false
}

View File

@ -1,32 +1,25 @@
// #docregion dsl
(function() {
// #docregion
// #docregion class-w-annotations
var AppComponent = ng
// #docregion component
.Component({
selector: 'my-app'
})
// #enddocregion
// #docregion view
.View({
template: '<h1>My First Angular 2 App</h1>'
})
// #enddocregion
// #docregion class
.Class({
constructor: function () { }
});
// #enddocregion
// #enddocregion
ng.Component({
selector: 'my-app',
template: '<h1>My First Angular 2 App</h1>'
})
.Class({
constructor: function () { }
});
// #enddocregion class-w-annotations
// #docregion bootstrap
document.addEventListener('DOMContentLoaded', function() {
ng.bootstrap(AppComponent);
});
// #enddocregion
// #enddocregion
// #enddocregion bootstrap
})();
// #enddocregion dsl
/* Non DSL Approach */
(function() {
@ -35,10 +28,8 @@ document.addEventListener('DOMContentLoaded', function() {
function AppComponent () {}
AppComponent.annotations = [
new ng.ComponentAnnotation({
selector: 'my-app'
}),
new ng.ViewAnnotation({
new ng.Component({
selector: 'my-app',
template: '<h1 id="output">My First Angular 2 App</h1>'
})
];

View File

@ -1,8 +1,8 @@
<!-- #docregion -->
<!DOCTYPE html>
<!-- #docregion -->
<html>
<head>
<script src="https://code.angularjs.org/2.0.0-alpha.34/angular2.sfx.dev.js"></script>
<script src="node_modules/angular2/bundles/angular2.sfx.dev.js"></script>
<script src="app.js"></script>
</head>
<body>

View File

@ -0,0 +1,18 @@
{
"name": "angular2-getting-started",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "live-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"angular2": "2.0.0-alpha.42"
},
"devDependencies": {
"live-server": "^0.8.1"
}
}

View File

@ -13,7 +13,7 @@
"guide": {
"icon": "list",
"title": "Step By Step Guide",
"title": "Developer Guide",
"banner": "Angular 2 is currently in Developer Preview. For <a href='https://docs.angularjs.org/guide'>Angular 1.X Resources</a> please visit <a href='https://angularjs.org/'>Angularjs.org</a>."
},

View File

@ -5,10 +5,6 @@
"title": "Step By Step Guide"
},
"gettingStarted": {
"title": "Getting Started"
},
"displaying-data": {
"title": "Displaying Data",
"intro": "Displaying data is job number one for any good application. In Angular, you bind data to elements in HTML templates and Angular automatically updates the UI as data changes."

View File

@ -1,200 +0,0 @@
include ../../../../_includes/_util-fns
:markdown
Let's start from zero and build a simple Angular 2 application in JavaScript.
.callout.is-helpful
header Don't want JavaScript?
:markdown
Although we're getting started in JavaScript, you can also write Angular 2 apps
in TypeScript and Dart by selecting either of those languages from the combo-box in the banner.
:markdown
We'll do it in four short steps
1. Create a new project folder and an *index.html*
1. Write the root component for our application in *app.js*
1. Bootstrap the app
1. Run it
.l-main-section
:markdown
## Create a project folder and an *index.html*
Create a new folder to hold our application project, perhaps like this:
pre.prettyprint.lang-bash
code mkdir firstNgApp && cd firstNgApp
:markdown
Then add a new `index.html` file to the project folder and enter the following HTML
+makeExample('gettingstarted/js/index.html', null, 'index.html')(format="")
.l-sub-section
:markdown
Our app loads two script files in the `<head>` element:
>***angular.js***, the Angular 2 library.
>***app.js***, the application JavaScript which we're about to write.
In the `<body>`, there's an element called `<my-app>`. This is a placeholder for the *root* of our
application. Angular will display our application content here.
.l-main-section
:markdown
## Write the *app* component
Create an *app.js* file with the following content:
+makeExample('gettingstarted/js/app.js', 'class-w-annotations')
:markdown
When we step back and squint, we see that
we're creating a visual component named **`appComponent`** by chaining three methods
originating in the global Angular namespace object called, **`ng`**.
```
var appComponent = ng
.Component({...})
.View({...})
.Class({...})
```
The **`Component`** method tells Angular that this is a component
controlling the element named "my-app".
+makeExample('gettingstarted/js/app.js', 'component')
:markdown
You may remember we added such an element to our *index.html* above.
The **`View`** method identifies the HTML template
that defines the visual appearance of the component.
+makeExample('gettingstarted/js/app.js', 'view')
:markdown
We're writing the HTML template inline
in this example. Later we'll move the HTML to a view template file and
assign the template's filename to the `templateUrl`.
We'll prefer that practice for all but the most trivial templates.
The **`Class`** method is where we implement the component itself,
giving it properties and methods that bind to the view and whatever
behavior is appropriate for this part of the UI.
+makeExample('gettingstarted/js/app.js', 'class')
:markdown
This component has the minimum implementation:
a *no-op* constructor function that does nothing because there is nothing to do.
We'll see more interesting component classes in future examples.
.l-main-section
:markdown
## Run it!
We need a file server to serve the static assets of our application (*index.html* and *app.js*).
If you have python on your machine, you're in luck: python ships with a basic static file server.
Open a terminal window and enter:
pre.prettyprint.lang-bash
code python -m SimpleHTTPServer 8000
:markdown
then point a browser to http://localhost:8000 which should display our simple text message:
figure.image-display
img(src='/resources/images/examples/setup-example1.png' alt="Example of Todo App")
:markdown
**If you don't have python**, you may have to install a server.
You might prefer one of the many node-based static servers such as
[http-server](https:/github.com/nodeapps/http-server "http-server"),
[superstatic](https://www.npmjs.com/package/superstatic "superstatic"), or
[live-server](https://www.npmjs.com/package/live-server "live-server").
:markdown
For this example we'll use **live-server** because it performs a live reload by default and it's
fun to watch the browser update as we make changes.
Open a terminal (or Windows/Linux command line) and enter:
pre.prettyprint.lang-bash
code npm install -g live-server
.callout.is-helpful
:markdown
Install [**node** and **npm**](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
first if you haven't already. They're indispensible front-end developer tools.
:markdown
After it finishes installing, start the server on port 8000
pre.prettyprint.lang-bash
code live-server --port=8000
:markdown
**live-server** loads the browser for us and refreshes the page as we make
changes to the application.
.l-main-section
:markdown
## Add TypeScript Type Definition Files (optional)
"*Wait*", you say, "*we're writing in JavaScript, not TypeScript!*".
Indeed we are. But code editors (such as [Visual Studio Code](https://code.visualstudio.com/) and
[Web Storm](https://www.jetbrains.com/webstorm/features/))
can improve the JavaScript development experience by providing type information and
displaying API documentation ("intellisense") based on TypeScript type definition files.
We can download type definitions files for third-party libraries such as Angular
from the [DefinitelyTyped](http://definitelytyped.org/) repository using the
[**tsd package manager**](https://www.npmjs.com/package/tsd "TSD Package Manager").
If you haven't already installed the *tsd*, do it now
with an npm command entered in a terminal or command window.
pre.prettyprint.lang-bash
code npm install -g tsd
:markdown
Now let's download and install the core set of type definitions files for Angular development
in the root directory of our application.
pre.prettyprint.lang-bash
code tsd install angular2 --save
:markdown
We'll find a ***typings*** folder in the root directory
with subfolders for each of the five downloaded type definition files (angular, es6-promise, rx, rx-lite, jasmine).
Type definition files have names ending in ***d.ts***.
There's also a summary ***tsd.d.ts*** file containing references to each of them.
Check your editor's documentation for instructions on using the *tsd.d.ts* file to
light up type checking and intellisense for these libraries.
.l-main-section
:markdown
## It's all a tree
We can think of Angular apps as a tree of components.
The `AppComponent` that we've been talking about acts as the top
level container - the root of the tree - for the rest of our application.
There's nothing special about the `AppComponent` name and we can use whatever makes sense to us.
We've pinned the root component to an element in the `index.html` file where our application will
render its view. The element is called `<my-app>` but there is nothing special about this
name either.
The *root component* loads the initial template for the application.
That template could load other components such as menu bars, views, and forms
that display information and respond to user gestures.
And these components could load yet more components until the browser page became a deep tree
of nested functionality.
We'll walk through examples of these scenarios in the following pages.

View File

@ -0,0 +1,261 @@
.callout.is-helpful
header Angular is in developer preview
p.
This quickstart does not reflect the final development process for writing apps with Angular.
The following setup is for those who want to try out Angular while it is in developer preview.
// STEP 1 - Create a project ##########################
.l-main-section
h2#section-create-project 1. Create a project
p.
This quickstart shows how to write your Angular components in TypeScript. You could instead choose
another language such as <a href="/docs/dart/latest/quickstart.html">Dart</a>, ES5, or ES6.
p.
The goal of this quickstart is to write a component in TypeScript that prints a string.
We assume you have already installed <a href="https://docs.npmjs.com/getting-started/installing-node">Node and npm</a>.
p.
To get started, create a new empty project directory. All the following commands should be run
from this directory.
p.
To get the benefits of TypeScript, we want to have the type definitions available for the compiler and the editor.
TypeScript type definitions are typically published in a repo called <a href="http://definitelytyped.org/">DefinitelyTyped</a>.
To fetch one of the type definitions to the local directory, we use the <a href="https://www.npmjs.com/package/tsd">tsd package manager</a>.
code-example.
$ npm install -g tsd@^0.6.0
$ tsd install angular2 es6-promise rx rx-lite
p.
Next, create two empty files, <code>index.html</code> and <code>app.ts</code>, both at the root of the project:
code-example.
$ touch app.ts index.html
// STEP 2 - Start the TypeScript compiler ##########################
.l-main-section
h2#start-tsc 2. Run the TypeScript compiler
p.
Since the browser doesn't understand TypeScript code, we need to run a compiler to translate
your code to browser-compliant JavaScript as you work. This quickstart uses the TypeScript
compiler in <code>--watch</code> mode, but it is also possible to do the translation in the browser as files
are loaded, or configure your editor or IDE to do it.
code-example.
$ npm install -g typescript@^1.5.0
$ tsc --watch -m commonjs -t es5 --emitDecoratorMetadata app.ts
.callout.is-helpful
p.
Windows users: if you get an error that an option is unknown, you are probably running
an older version of TypeScript.
See <a href="http://stackoverflow.com/questions/23267858/how-do-i-install-typescript">
Stack Overflow: How do I install Typescript</a>
// STEP 3 - Import Angular ##########################
.l-main-section
h2#section-transpile 3. Import Angular
p Inside of <code>app.ts</code>, import the type definitions from Angular:
code-example.
/// &lt;reference path="typings/angular2/angular2.d.ts" /&gt;
p Now your editor should be able to complete the available imports:
code-example.
import {Component, View, bootstrap} from 'angular2/angular2';
p.
The above import statement uses ES6 module syntax to import three symbols from the Angular module.
The module will load at runtime.
// STEP 4 - Create a component ##########################
.l-main-section
h2#section-angular-create-account 4. Define a component
p.
Components structure and represent the UI. This quickstart demonstrates the process of creating a component
that has an HTML tag named <strong><code>&lt;my-app&gt;</code></strong>.
p.
A component consists of two parts, the <strong>component controller</strong>
which is an ES6 class, and the <strong>decorators</strong> which tell Angular
how to place the component into the page.
code-example(language="javascript" format="linenums").
// Annotation section
@Component({
selector: 'my-app'
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;'
})
// Component controller
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
.l-sub-section
h3 @Component and @View annotations
p.
A component annotation describes details about the component. An annotation can be identified by its at-sign (<code>@</code>).
p.
The <code>@Component</code> annotation defines the HTML tag for the component by specifying the component's CSS selector.
p.
The <code>@View</code> annotation defines the HTML that represents the component. The component you wrote uses an inline template, but you can also have an external template. To use an external template, specify a <code>templateUrl</code> property and give it the path to the HTML file.
code-example(language="javascript" format="linenums").
@Component({
selector: 'my-app' // Defines the &lt;my-app&gt;&lt;/my-app&gt; tag
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;' // Defines the inline template for the component
})
p.
The annotations above specify an HTML tag of <code>&lt;my-app&gt;</code>
and a template of <code ng-non-bindable>&lt;h1&gt;Hello &#123;&#123; name }}&lt;/h1&gt;</code>.
.l-sub-section
h3 The template and the component controller
p.
The component controller is the backing of the component's template. This component
controller uses TypeScript <code>class</code> syntax.
code-example(language="javascript" format="linenums").
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
p.
Templates read from their component controllers. Templates have access to any properties
or functions placed on the component controller.
p.
The template above binds to a <code>name</code> property through
the double-mustache syntax (<code ng-non-bindable>{{ ... }}</code>).
The body of the constructor assigns "Alice" to the name property. When the
template renders, "Hello Alice" appears instead of
<span ng-non-bindable>"Hello {{ name }}"</span>.
// STEP 5 - Bootstrap ##########################
.l-main-section
h2#section-transpile 5. Bootstrap
p.
At the bottom of <code>app.ts</code>, call the <code>bootstrap()</code> function
to load your new component into its page:
code-example(language="javaScript").
bootstrap(MyAppComponent);
p.
The <code>bootstrap()</code> function takes a
component as a parameter, enabling the component
(as well as any child components it contains) to render.
// STEP 6 - Declare the HTML ##########################
.l-main-section
h2#section-angular-create-account 6. Declare the HTML
p.
Inside the <code>head</code> tag of <code>index.html</code>,
include the traceur-runtime and the Angular bundle.
Instantiate the <code>my-app</code> component in the <code>body</code>.
code-example(language="html" format="linenums").
&lt;!-- index.html --&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- The app component created in app.ts --&gt;
&lt;my-app&gt;&lt;/my-app&gt;
&lt;/body&gt;
&lt;/html&gt;
// STEP 7 - Declare the HTML ##########################
.l-main-section
h2#section-load-component-module 7. Load the component
p.
The last step is to load the module for the <code>my-app</code> component.
To do this, we'll use the System library.
.l-sub-section
h3 System.js
p.
<a href="https://github.com/systemjs/systemjs">System</a> is a third-party open-source library that
adds ES6 module loading functionality to browsers.
p.
Add the System.js dependency in the <code>&lt;head&gt;</code> tag, so that
it looks like:
code-example(language="html" format="linenums").
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://jspm.io/system@0.16.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
p.
Add the following module-loading code:
code-example(language="html" format="linenums").
&lt;my-app&gt;&lt;/my-app&gt;
&lt;script&gt;System.import('app');&lt;/script&gt;
// STEP 8 - Run a local server ##########################
.l-main-section
h2#section-load-component-module 8. Run a local server
p Run a local HTTP server, and view <code>index.html</code>.
p.
If you don't already have an HTTP server,
you can install one using <code>npm install -g http-server</code>.
(If that results in an access error, then you might need to use
<code><b>sudo</b> npm ...</code>.)
p For example:
code-example.
# From the directory that contains index.html:
npm install -g http-server # Or sudo npm install -g http-server
http-server # Creates a server at localhost:8080
# In a browser, visit localhost:8080/index.html
// WHAT'S NEXT... ##########################
.l-main-section
h2#section-transpile Great job! We'll have the next steps out soon.

View File

@ -1,261 +1,195 @@
.callout.is-helpful
header Angular is in developer preview
p.
This quickstart does not reflect the final development process for writing apps with Angular.
The following setup is for those who want to try out Angular while it is in developer preview.
include ../../../_includes/_util-fns
// STEP 1 - Create a project ##########################
.l-main-section
h2#section-create-project 1. Create a project
p.
This quickstart shows how to write your Angular components in TypeScript. You could instead choose
another language such as <a href="/docs/dart/latest/quickstart.html">Dart</a>, ES5, or ES6.
p.
The goal of this quickstart is to write a component in TypeScript that prints a string.
We assume you have already installed <a href="https://docs.npmjs.com/getting-started/installing-node">Node and npm</a>.
p.
To get started, create a new empty project directory. All the following commands should be run
from this directory.
p.
To get the benefits of TypeScript, we want to have the type definitions available for the compiler and the editor.
TypeScript type definitions are typically published in a repo called <a href="http://definitelytyped.org/">DefinitelyTyped</a>.
To fetch one of the type definitions to the local directory, we use the <a href="https://www.npmjs.com/package/tsd">tsd package manager</a>.
code-example.
$ npm install -g tsd@^0.6.0
$ tsd install angular2 es6-promise rx rx-lite
p.
Next, create two empty files, <code>index.html</code> and <code>app.ts</code>, both at the root of the project:
code-example.
$ touch app.ts index.html
// STEP 2 - Start the TypeScript compiler ##########################
.l-main-section
h2#start-tsc 2. Run the TypeScript compiler
p.
Since the browser doesn't understand TypeScript code, we need to run a compiler to translate
your code to browser-compliant JavaScript as you work. This quickstart uses the TypeScript
compiler in <code>--watch</code> mode, but it is also possible to do the translation in the browser as files
are loaded, or configure your editor or IDE to do it.
code-example.
$ npm install -g typescript@^1.5.0
$ tsc --watch -m commonjs -t es5 --emitDecoratorMetadata app.ts
:markdown
Let's start from zero and build a simple Angular 2 application in JavaScript.
.callout.is-helpful
p.
Windows users: if you get an error that an option is unknown, you are probably running
an older version of TypeScript.
See <a href="http://stackoverflow.com/questions/23267858/how-do-i-install-typescript">
Stack Overflow: How do I install Typescript</a>
header Don't want JavaScript?
:markdown
Although we're getting started in JavaScript, you can also write Angular 2 apps
in TypeScript and Dart by selecting either of those languages from the combo-box in the banner.
// STEP 3 - Import Angular ##########################
.l-main-section
h2#section-transpile 3. Import Angular
:markdown
We'll do it in six short steps
1. Create a project folder
1. Install essential libraries
1. Write the root component for our application in *app.js*
1. Bootstrap the app
1. Create an *index.html*
1. Run it
p Inside of <code>app.ts</code>, import the type definitions from Angular:
code-example.
/// &lt;reference path="typings/angular2/angular2.d.ts" /&gt;
p Now your editor should be able to complete the available imports:
code-example.
import {Component, View, bootstrap} from 'angular2/angular2';
p.
The above import statement uses ES6 module syntax to import three symbols from the Angular module.
The module will load at runtime.
// STEP 4 - Create a component ##########################
.l-main-section
h2#section-angular-create-account 4. Define a component
:markdown
## Create a project folder
**Create a new folder** to hold our application project, perhaps like this:
```
mkdir angular2-getting-started
cd angular2-getting-started
```
## Install essential libraries
p.
Components structure and represent the UI. This quickstart demonstrates the process of creating a component
that has an HTML tag named <strong><code>&lt;my-app&gt;</code></strong>.
We'll use the **npm package manager** to install packages for
the libraries and development tools we need:
p.
A component consists of two parts, the <strong>component controller</strong>
which is an ES6 class, and the <strong>decorators</strong> which tell Angular
how to place the component into the page.
>angular2 - the Angular 2 library.
>[live-server](https://www.npmjs.com/package/live-server "Live-server")
a static file server that reloads the browser when files change.
We could reference the libraries on the web or download them to our project.
That isn't a sustainable development process and package loading with npm is really
easy once we have it installed.
code-example(language="javascript" format="linenums").
// Annotation section
@Component({
selector: 'my-app'
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;'
})
// Component controller
class MyAppComponent {
name: string;
.alert.is-helpful
:markdown
Don't have npm? [Get it now](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
because we're going to use it now and repeatedly throughout this documentation.
:markdown
**Open** a terminal window and enter these commands:
```
npm init -y
npm i angular2@2.0.0-alpha.42 --save --save-exact
npm i live-server --save-dev
```
These commands both *install* the packages and *create* an npm configuration
file named `package.json`.
The essence of our `package.json` should look like this:
constructor() {
this.name = 'Alice';
}
}
+makeJson('gettingstarted/js/package.json', { paths: 'name, version, dependencies, devDependencies'})
:markdown
There is also a `scripts` section. **Find and replace** it with the following:
+makeJson('gettingstarted/js/package.json', { paths: 'scripts'})
:markdown
We've just extended our project world with a script command that we'll be running very soon.
.l-main-section
:markdown
## Our first Angular component
Add a new file called *app.js* and paste the following lines:
+makeExample('gettingstarted/js/app.js', 'class-w-annotations')
:markdown
We're creating a visual component named **`appComponent`** by chaining the
`Component` and `Class` methods that belong to the **global Angular namespace, `ng`**.
```
var AppComponent = ng
.Component({...})
.Class({...})
```
The **`Component`** method takes a configuration object with two
properties. The `selector` property tells Angular that this is a component
controlling a host element named "my-app".
Angular creates and displays an instance of our `AppComponent`
wherever it encounters a `my-app` element.
The `template` property defines the visual appearance of the component.
We're writing the HTML template inline in this example.
Later we'll move the HTML to a view template file and
assign the template's filename to the `templateUrl` property.
We'll prefer that practice for all but the most trivial templates.
The **`Class`** method is where we implement the component itself,
giving it properties and methods that bind to the view and whatever
behavior is appropriate for this part of the UI.
This component class has the bare minimum implementation:
a *no-op* constructor function that does nothing because there is nothing to do.
We'll see more interesting component classes in future examples.
.l-main-section
:markdown
## Bootstrap the app
We need to do something to put our application in motion.
Add the following to the bottom of the `app.js` file:
+makeExample('gettingstarted/js/app.js', 'bootstrap')
:markdown
We'll wait for the browser to tell us that it has finished loading
all content and then we'll call the Angular `bootstrap` method.
The `bootstrap` method tells Angular to start the application with our
`AppComponent` at the application root.
We'd be correct to guess that someday our application will
consist of more components arising in tree-like fashion from this root.
### Wrapped in an IIFE
We don't want to pollute the global namespace.
We don't need an application namespace yet.
So we'll surround the code in a simple IIFE
("Immediately Invoked Function Execution")
wrapper.
Here is the entire file:
+makeExample('gettingstarted/js/app.js', 'dsl')
.l-main-section
:markdown
## Create an *index.html*
**Add a new `index.html`** file to the project folder and enter the following HTML
+makeExample('gettingstarted/js/index.html', null, 'index.html')(format="")
.l-sub-section
h3 @Component and @View annotations
:markdown
Our app loads two script files in the `<head>` element:
p.
A component annotation describes details about the component. An annotation can be identified by its at-sign (<code>@</code>).
p.
The <code>@Component</code> annotation defines the HTML tag for the component by specifying the component's CSS selector.
p.
The <code>@View</code> annotation defines the HTML that represents the component. The component you wrote uses an inline template, but you can also have an external template. To use an external template, specify a <code>templateUrl</code> property and give it the path to the HTML file.
>***angular2.sfx.dev.js***, the Angular 2 development library that puts
Angular in the global `ng` namespace.
code-example(language="javascript" format="linenums").
@Component({
selector: 'my-app' // Defines the &lt;my-app&gt;&lt;/my-app&gt; tag
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;' // Defines the inline template for the component
})
>***app.js***, the application JavaScript we just wrote.
p.
The annotations above specify an HTML tag of <code>&lt;my-app&gt;</code>
and a template of <code ng-non-bindable>&lt;h1&gt;Hello &#123;&#123; name }}&lt;/h1&gt;</code>.
In the `<body>`, there's an element called `<my-app>`.
This is the placeholder for the *root* of the
application. Angular displays our application here.
.l-sub-section
h3 The template and the component controller
p.
The component controller is the backing of the component's template. This component
controller uses TypeScript <code>class</code> syntax.
code-example(language="javascript" format="linenums").
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
p.
Templates read from their component controllers. Templates have access to any properties
or functions placed on the component controller.
p.
The template above binds to a <code>name</code> property through
the double-mustache syntax (<code ng-non-bindable>{{ ... }}</code>).
The body of the constructor assigns "Alice" to the name property. When the
template renders, "Hello Alice" appears instead of
<span ng-non-bindable>"Hello {{ name }}"</span>.
// STEP 5 - Bootstrap ##########################
.l-main-section
h2#section-transpile 5. Bootstrap
:markdown
## Run it!
p.
At the bottom of <code>app.ts</code>, call the <code>bootstrap()</code> function
to load your new component into its page:
We need a file server to serve the static assets of our application
(*index.html* and *app.js*).
code-example(language="javaScript").
bootstrap(MyAppComponent);
For this example we'll use the **live-server** that we installed with `npm`
because it performs a live reload by default and it's
fun to watch the browser update as we make changes.
Open a terminal (or Windows/Linux command line) and enter:
p.
The <code>bootstrap()</code> function takes a
component as a parameter, enabling the component
(as well as any child components it contains) to render.
pre.prettyprint.lang-bash
code npm start
.alert.is-helpful
:markdown
That's the `npm` command we added earlier to the `scripts` section of `package.json`
:markdown
**live-server** loads the browser for us and refreshes the page as we make
changes to the application.
In a few moments, a browser tab should open and display
// STEP 6 - Declare the HTML ##########################
.l-main-section
figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
h2#section-angular-create-account 6. Declare the HTML
:markdown
### Make some changes
The `live-server` detects changes to our files and refreshes the browser page for us automatically.
p.
Inside the <code>head</code> tag of <code>index.html</code>,
include the traceur-runtime and the Angular bundle.
Instantiate the <code>my-app</code> component in the <code>body</code>.
Try changing the message to "My SECOND Angular 2 app".
The `live-server` sees that change and reloads the browser.
code-example(language="html" format="linenums").
&lt;!-- index.html --&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- The app component created in app.ts --&gt;
&lt;my-app&gt;&lt;/my-app&gt;
&lt;/body&gt;
&lt;/html&gt;
// STEP 7 - Declare the HTML ##########################
.l-main-section
h2#section-load-component-module 7. Load the component
p.
The last step is to load the module for the <code>my-app</code> component.
To do this, we'll use the System library.
.l-sub-section
h3 System.js
p.
<a href="https://github.com/systemjs/systemjs">System</a> is a third-party open-source library that
adds ES6 module loading functionality to browsers.
p.
Add the System.js dependency in the <code>&lt;head&gt;</code> tag, so that
it looks like:
code-example(language="html" format="linenums").
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://jspm.io/system@0.16.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
p.
Add the following module-loading code:
code-example(language="html" format="linenums").
&lt;my-app&gt;&lt;/my-app&gt;
&lt;script&gt;System.import('app');&lt;/script&gt;
// STEP 8 - Run a local server ##########################
.l-main-section
h2#section-load-component-module 8. Run a local server
p Run a local HTTP server, and view <code>index.html</code>.
p.
If you don't already have an HTTP server,
you can install one using <code>npm install -g http-server</code>.
(If that results in an access error, then you might need to use
<code><b>sudo</b> npm ...</code>.)
p For example:
code-example.
# From the directory that contains index.html:
npm install -g http-server # Or sudo npm install -g http-server
http-server # Creates a server at localhost:8080
# In a browser, visit localhost:8080/index.html
// WHAT'S NEXT... ##########################
.l-main-section
h2#section-transpile Great job! We'll have the next steps out soon.
Keep `live-server` running in this terminal window and keep trying changes.
You can stop it anytime with `Ctrl-C`.
**Congratulations! We are in business** ... and ready to take
our app to the next level.

View File

@ -13,7 +13,7 @@
"guide": {
"icon": "list",
"title": "Step By Step Guide",
"title": "Developer Guide",
"banner": "Angular 2 is currently in Developer Preview. For <a href='https://docs.angularjs.org/guide'>Angular 1.X Resources</a> please visit <a href='https://angularjs.org/'>Angularjs.org</a>."
},

View File

@ -5,10 +5,6 @@
"title": "Step By Step Guide"
},
"gettingStarted": {
"title": "Getting Started"
},
"displaying-data": {
"title": "Displaying Data",
"intro": "Displaying data is job number one for any good application. In Angular, you bind data to elements in HTML templates and Angular automatically updates the UI as data changes."

View File

@ -1,326 +1,316 @@
include ../../../../_includes/_util-fns
:markdown
In this chapter well setup the environment for testing our sample application and write a few easy Jasmine tests of the apps simplest parts.
In this chapter well setup the environment for testing our sample application and write a few easy Jasmine tests of the apps simplest parts.
We'll learn:
- to test one of our application classes
- why we prefer our test files to be next to their corresponding source files
- to run tests with an `npm` command
- load the test file with systemJS
We learn:
- to test one of our application classes
- why we prefer our test files to be next to their corresponding source files
- to run tests with an `npm` command
- load the test file with systemJS
.callout.is-helpful
header Prior Knowledge
:markdown
The Unit Testing chapters build upon each other. We recommend reading them in order.
We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools
we introduced in the [QuickStart](../quickstart.html) and
the [Tour of Heroes](./toh-pt1.html) tutorial
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
:markdown
## Create the test-runner HTML
## Prerequisites
Step away from the Jasmine 101 folder and turn to the root folder of the application that we downloaded in the previous chapter.
We assume
Locate the `src` folder that contains the application `index.html`
- youve learned the basics of Angular 2, from this Developers Guide or elsewhere. We wont re-explain the Angular 2 architecture, its key parts, or the recommended development techniques.
youve read the [Jasmine 101](./jasmine-testing-101.html) chapter.
- youve downloaded the [Heroes application were about to test](./#). <!-- TODO add link -->
Create a new, sibling HTML file, ** `unit-tests.html` ** and copy over the same basic material from the `unit-tests.html` in the [Jasmine 101](./jasmine-testing-101.html) chapter.
## Create the test-runner HTML
```
<html>
<title>Ng App Unit Tests</title>
<link rel="stylesheet" href="../node_modules/jasmine/lib/jasmine.css">
Step away from the Jasmine 101 folder and turn to the root folder of the application that we downloaded in the previous chapter.
<script src="../node_modules/jasmine/lib/jasmine.js"></script>
<script src="../node_modules/jasmine/lib/jasmine-html.js"></script>
<script src="../node_modules/jasmine/lib/boot.js"></script>
Locate the `src` folder that contains the application `index.html`
</head>
Create a new, sibling HTML file, ** `unit-tests.html` ** and copy over the same basic material from the `unit-tests.html` in the [Jasmine 101](./jasmine-testing-101.html) chapter.
<body>
</body>
```
<html>
<title>Ng App Unit Tests</title>
<link rel="stylesheet" href="../node_modules/jasmine/lib/jasmine.css">
</html>
```
<script src="../node_modules/jasmine/lib/jasmine.js"></script>
<script src="../node_modules/jasmine/lib/jasmine-html.js"></script>
<script src="../node_modules/jasmine/lib/boot.js"></script>
Were picking up right where we left off. All weve done is change the title.
</head>
## Update `package.json` for testing
<body>
</body>
Well assume that the application has `package.json` file that looks more or less like
the one we prescribed in the in the “Install npm packages locally” section of the
[QuickStart](../quickstart.html).
</html>
```
Were picking up right where we left off. All weve done is change the title.
## Update `package.json` for testing
Well assume that the application has `package.json` file that looks more or less like
the one we prescribed in the in the “Install npm packages locally” section of the [Getting Started] chapter.
We must install the Jasmine package as well:
We must install the Jasmine package as well:
pre.prettyprint.lang-bash
code npm install jasmine-core --save-dev --save-exact
code npm install jasmine-core --save-dev --save-exact
.alert.is-important Be sure to install <code>jasmine-core</code> , not <code>jasmine</code>!
:markdown
Update the Typescript typings aggregation file (`tsd.d.ts`) with the Jasmine typings file.
Lets make one more change to the `package.json` script commands.
pre.prettyprint.lang-bash
code npm tsd
**Open the `package.json` ** and scroll to the `scripts` node. Look for the command named `test`. Change it to:
:markdown
Lets make one more change to the `package.json` script commands.
"test": "live-server --open=src/unit-tests.html"
**Open the `package.json` ** and scroll to the `scripts` node. Look for the command named `test`. Change it to:
That command will launch `live-server` and open a browser to the `unit-tests.html` page we just wrote.
"test": "live-server --open=src/unit-tests.html"
## First app tests
That command will launch `live-server` and open a browser to the `unit-tests.html` page we just wrote.
Believe it or not … we could start testing *some* of our app right away. For example, we can test the `Hero` class:
```
let nextId = 30;
## First app tests
export class Hero {
constructor(
public id?: number,
public name?: string,
public power?: string,
public alterEgo?: string
) {
this.id = id || nextId++;
}
Believe it or not … we could start testing *some* of our app right away. For example, we can test the `Hero` class:
```
let nextId = 30;
clone() { return Hero.clone(this); }
export class Hero {
constructor(
public id?: number,
public name?: string,
public power?: string,
public alterEgo?: string
) {
this.id = id || nextId++;
}
static clone = (h:any) => new Hero(h.id, h.name, h.alterEgo, h.power);
clone() { return Hero.clone(this); }
static setNextId = (next:number) => nextId = next;
}
```
static clone = (h:any) => new Hero(h.id, h.name, h.alterEgo, h.power);
Lets add a couple of simple tests in the `<body>` element.
static setNextId = (next:number) => nextId = next;
}
```
First, well load the JavaScript file that defines the `Hero` class.
Lets add a couple of simple tests in the `<body>` element.
```
<!-- load the application's Hero definition -->
<script src="app/hero.js"></script>
```
First, well load the JavaScript file that defines the `Hero` class.
Next, well add an inline script element with the `Hero`tests themselves
```
<!-- load the application's Hero definition -->
<script src="app/hero.js"></script>
```
```
<script>
// Demo only!
describe('Hero', function() {
Next, well add an inline script element with the `Hero`tests themselves
it('has name given in the constructor', function() {
var hero = new Hero(1, 'Super Cat');
expect(hero.name).toEqual('Super Cat');
});
```
<script>
// Demo only!
describe('Hero', function() {
it('has the id given in the constructor', function() {
var hero = new Hero(1, 'Super Cat');
expect(hero.id).toEqual(1);
});
it('has name given in the constructor', function() {
var hero = new Hero(1, 'Super Cat');
expect(hero.name).toEqual('Super Cat');
});
});
</script>
```
it('has the id given in the constructor', function() {
var hero = new Hero(1, 'Super Cat');
expect(hero.id).toEqual(1);
});
Thats the basic Jasmine we learned back in “Jasmine 101”.
});
</script>
```
Notice that we surrounded our tests with ** `describe('Hero')` **.
Thats the basic Jasmine we learned back in “Jasmine 101”.
**By convention, our test always begin with a `describe` that identifies the application part under test.**
Notice that we surrounded our tests with ** `describe('Hero')` **.
The description should be sufficient to identify the tested application part and its source file. Almost any convention will do as long as you and your team follow it consistently and are never confused.
**By convention, our test always begin with a `describe` that identifies the application part under test.**
## Run the tests
The description should be sufficient to identify the tested application part and its source file. Almost any convention will do as long as you and your team follow it consistently and are never confused.
Open one terminal window and run the watching compiler command: `npm run tsc`
## Run the tests
Open another terminal window and run live-server: `npm test`
Open one terminal window and run the watching compiler command: `npm run tsc`
Open another terminal window and run live-server: `npm test`
The browser should launch and display the two passing tests:
The browser should launch and display the two passing tests:
figure.image-display
img(src='/resources/images/devguide/first-app-tests/passed-2-specs-0-failures.png' style="width:400px;" alt="Two passing tests")
img(src='/resources/images/devguide/first-app-tests/passed-2-specs-0-failures.png' style="width:400px;" alt="Two passing tests")
:markdown
## Critique
## Critique
Is this `Hero` class even worth testing? Its essentially a property bag with almost no logic. Maybe we should have tested the cloning feature. Maybe we should have tested id generation. We didnt bother because there wasnt much to learn by doing that.
Is this `Hero` class even worth testing? Its essentially a property bag with almost no logic. Maybe we should have tested the cloning feature. Maybe we should have tested id generation. We didnt bother because there wasnt much to learn by doing that.
Its more important to take note of the<span style="background-color: yellow;"> //Demo only </span>comment in the `unit-tests.html`.
Its more important to take note of the `//Demo only` comment in the `unit-tests.html`.
** Well never write real tests in the HTML this way**. Its nice that we can write *some* of our application tests directly in the HTML. But dumping all of our tests into HTML is not sustainable and even if we didnt mind that approach, we could only test a tiny fraction of our app this way.
** Well never write real tests in the HTML this way**. Its nice that we can write *some* of our application tests directly in the HTML. But dumping all of our tests into HTML is not sustainable and even if we didnt mind that approach, we could only test a tiny fraction of our app this way.
We need to relocate these tests to a separate file. Lets do that next.
We need to relocate these tests to a separate file. Lets do that next.
## Where do tests go?
## Where do tests go?
Some people like to keep their tests in a `tests` folder parallel to the application source folder.
Some people like to keep their tests in a `tests` folder parallel to the application source folder.
We are not those people. We like our unit tests to be close to the source code that they test. We prefer this approach because
- The tests are easy to find
- We see at a glance if an application part lacks tests.
- Nearby tests can teach us about how the part works; they express the developers intention and reveal how the developer thinks the part should behave under a variety of circumstances.
- When we move the source (inevitable), we remember to move the test.
- When we rename the source file (inevitable), we remember to rename the test file.
We are not those people. We like our unit tests to be close to the source code that they test. We prefer this approach because
- The tests are easy to find
- We see at a glance if an application part lacks tests.
- Nearby tests can teach us about how the part works; they express the developers intention and reveal how the developer thinks the part should behave under a variety of circumstances.
- When we move the source (inevitable), we remember to move the test.
- When we rename the source file (inevitable), we remember to rename the test file.
We cant think of a downside. The server doesnt care where they are. They are easy to find and distinguish from application files when named conventionally.
We cant think of a downside. The server doesnt care where they are. They are easy to find and distinguish from application files when named conventionally.
You may put your tests elsewhere if you wish. Were putting ours inside the app, next to the source files that they test.
You may put your tests elsewhere if you wish. Were putting ours inside the app, next to the source files that they test.
## First spec file
## First spec file
**Create** a new file, ** `hero.spec.ts` ** in `src/app` next to `hero.ts`.
**Create** a new file, ** `hero.spec.ts` ** in `src/app` next to `hero.ts`.
Notice the “.spec” suffix in the test files filename, appended to the name of the file holding the application part were testing.
Notice the “.spec” suffix in the test files filename, appended to the name of the file holding the application part were testing.
.alert.is-important All of our unit test files follow this .spec naming pattern.
.alert.is-important All of our unit test files follow this .spec naming pattern.
:markdown
Move the tests we just wrote in`unit-tests.html` to `hero.spec.ts` and convert them from JavaScript into TypeScript:
Move the tests we just wrote in`unit-tests.html` to `hero.spec.ts` and convert them from JavaScript into TypeScript:
```
import {Hero} from './hero';
```
import {Hero} from './hero';
describe('Hero', () => {
describe('Hero', () => {
it('has name given in the constructor', () => {
let hero = new Hero(1, 'Super Cat');
expect(hero.name).toEqual('Super Cat');
});
it('has name given in the constructor', () => {
let hero = new Hero(1, 'Super Cat');
expect(hero.name).toEqual('Super Cat');
});
it('has id given in the constructor', () => {
let hero = new Hero(1, 'Super Cat');
expect(hero.id).toEqual(1);
});
})
it('has id given in the constructor', () => {
let hero = new Hero(1, 'Super Cat');
expect(hero.id).toEqual(1);
});
})
```
```
**Stop and restart the TypeScript compiler**
### Import the part were testing
.alert.is-important While the TypeScript compiler is watching for changes to files, it doesnt always pick up new files to compile.
During our conversion to TypeScript, we added an `import {Hero} from './hero' ` statement.
:markdown
### Typing problems
If we forgot this import, a TypeScript-aware editor would warn us, with a squiggly red underline, that it cant find the definition of the `Hero` class.
The editor may complain that it doesnt recognize `describe`, `beforeEach`, `it`, and `expect`. These are among the many Jasmine objects in the global namespace.
TypeScript doesnt know what a `Hero` is. It doesnt know about the script tag back in the `unit-tests.html` that loads the `hero.js` file.
We can cure the complaints and get intellisense support by adding the Jasmine typings file:
### Update unit-tests.html
Open a new terminal window in the `src` folder and run
Next we update the `unit-tests.html` with a reference to our new `hero-spec.ts` file. Delete the inline test code. The revised pertinent HTML looks like this:
pre.prettyprint.lang-bash
code tsd reinstall jasmine --save
<script src="app/hero.js"></script>
<script src="app/hero.spec.js"></script>
:markdown
Refresh the editor and those particular complaints should disappear
## Run and Fail
### Import the part were testing
During our conversion to TypeScript, we added an `import {Hero} from './hero' ` statement.
If we forgot this import, a TypeScript-aware editor would warn us, with a squiggly red underline, that it cant find the definition of the `Hero` class.
TypeScript doesnt know what a `Hero` is. It doesnt know about the script tag back in the `unit-tests.html` that loads the `hero.js` file.
### Update unit-tests.html
Next we update the `unit-tests.html` with a reference to our new `hero-spec.ts` file. Delete the inline test code. The revised pertinent HTML looks like this:
<script src="app/hero.js"></script>
<script src="app/hero.spec.js"></script>
## Run and Fail
Look over at the browser (live-server will have reloaded it). The browser displays
Look over at the browser (live-server will have reloaded it). The browser displays
figure.image-display
img(src='/resources/images/devguide/first-app-tests/Jasmine-not-running-tests.png' style="width:400px;" alt="Jasmine not running any tests")
img(src='/resources/images/devguide/first-app-tests/Jasmine-not-running-tests.png' style="width:400px;" alt="Jasmine not running any tests")
:markdown
Thats Jasmine saying “**things are _so_ bad that _Im not running any tests_.**”
Thats Jasmine saying “**things are _so_ bad that _Im not running any tests_.**”
Open the browsers Developer Tools (F12, Ctrl-Shift-i). Theres an error:
Open the browsers Developer Tools (F12, Ctrl-Shift-i). Theres an error:
```
Uncaught ReferenceError: exports is not defined
```
`Uncaught ReferenceError: exports is not defined`
## Load tests with systemjs
## Load tests with systemjs
The immediate cause of the error is the `export` statement in `hero.ts`.
That error was there all along.
It wasnt a problem until we tried to `import` the `Hero` class in our tests.
The immediate cause of the error is the `export` statement in `hero.ts`. That error was there all along. It wasnt a problem until we tried to `import` the `Hero` class in our tests.
Our test environment lacks support for module loading.
Apparently we cant simply load our application and test scripts like we do with 3rd party JavaScript libraries.
Our test environment lacks support for module loading. Apparently we cant simply load our application and test scripts like we do with 3rd party JavaScript libraries.
We are committed to module loading in our application.
Our app will call `import`. Our tests must do so too.
We are committed to module loading in our application. Our app will call `import`. Our tests must do so too.
We add module loading support in four steps:
We add module loading support in four steps:
1. add the *systemjs* module management library
1. configure *systemjs* to look for JavaScript files by default
1. import our test files
1. tell Jasmine to run the imported tests
1. add the *systemjs* module management library
1. configure *systemjs* to look for JavaScript files by default
1. import our test files
1. tell Jasmine to run the imported tests
These steps are all clearly visible, in exactly that order, in the following lines that
replace the `<body>` contents in `unit-tests.html`:
These steps are all clearly visible, in exactly that order, in the following lines that
replace the `<body>` contents in `unit-tests.html`:
```
<body>
<!-- #1. add the system.js library -->
<script src="../node_modules/systemjs/dist/system.src.js"></script>
```
<body>
<!-- #1. add the system.js library -->
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<script>
// #2. Configure systemjs to use the .js extension
// for imports from the app folder
System.config({
packages: {
'app': {defaultExtension: 'js'}
}
});
<script>
// #2. Configure systemjs to use the .js extension
// for imports from the app folder
System.config({
packages: {
'app': {defaultExtension: 'js'}
}
});
// #3. Import the spec file explicitly
System.import('app/hero.spec')
// #3. Import the spec file explicitly
System.import('app/hero.spec')
// #4. wait for all imports to load ...
// then re-execute `window.onload` which
// triggers the Jasmine test-runner start
// or explain what went wrong
.then(window.onload)
.catch(console.error.bind(console));
</script>
</body>
```
// #4. wait for all imports to load ...
// then re-execute `window.onload` which
// triggers the Jasmine test-runner start
// or explain what went wrong
.then(window.onload)
.catch(console.error.bind(console));
</script>
</body>
```
Look in the browser window. Our tests pass once again.
Look in the browser window. Our tests pass once again.
figure.image-display
img(src='/resources/images/devguide/first-app-tests/test-passed-once-again.png' style="width:400px;" alt="Tests passed once again")
img(src='/resources/images/devguide/first-app-tests/test-passed-once-again.png' style="width:400px;" alt="Tests passed once again")
:markdown
## Observations
## Observations
System.js demands that we specify a default extension for the filenames that correspond to whatever it is asked to import. Without that default, it would translate an import statement such as `import {Hero} from ./here` to a request for the file named `hero`.
### System.config
System.js demands that we specify a default extension for the filenames that correspond to whatever it is asked to import.
Without that default, it would translate an import statement such as `import {Hero} from ./here` to a request for the file named `hero`.
Not `hero.js`. Just plain `hero`. Our server error with “404 - not found” because it doesnt have a file of that name.
Not `hero.js`. Just plain `hero`. Our server error with “404 - not found” because it doesnt have a file of that name.
Once configured with a default extension of js,&nbsp; Systemjs requests `hero.js` which *does* exist and is promptly returned by our server.
When configured with a default extension of js, systemjs requests `hero.js` which *does* exist and is promptly returned by our server.
### Asynchronous System.import
The call to `System.import` shouldnt surprise us but its asynchronous nature might.
If we ponder this for a moment, we realize that it must be asynchronous because
System.js may have to fetch the corresponding JavaScript file from the server.
Accordingly, `System.import` returns a promise and we must wait for that promise to resolve.
Only then can Jasmine start evaluating the imported tests.
The call to `System.import` doesnt surprise us. But its asynchronous nature might. Of course it must be asynchronous; it probably has to fetch the corresponding JavaScript file from the server.
### window.onload
Jasmine doesnt have a `start` method. It wires its own start to the browser windows `load` event.
That makes sense if were loading our tests with script tags.
The browser raises the `load` event when it finishes loading all scripts.
`System.import` returns a promise. We wait for that promise to resolve and only then can Jasmine start evaluating the imported tests.
But were not loading test scripts inline anymore.
Were using the systemjs module loader and it wont be done until long after the browser raised the `load` event.
Meanwhile, Jasmine started and ran to completion … with no tests to evaluate … before the import completed.
Why do we call `window.onload` to start Jasmine? Jasmine doesnt have a `start` method. It wires its own start to the browser windows `load` event.
So we must wait until the import completes and only then call the window `onLoad` handler.
Jasmine re-starts, this time with our imported test queued up.
That makes sense if were loading our tests with script tags. The browser raise the `load` event when it finishes loading all scripts.
## Whats Next?
We are able to test a part of our application with simple Jasmine tests.
The part was a stand-alone class that made no mention or use of Angular.
But were not loading test scripts inline anymore. Were using the systemjs module loader and it wont be done until long after the browser raised the `load` event. Jasmine already started and ran to completion … with no tests to evaluate … before the import completed.
Thats not rare but its not typical either. Most of our application parts make some use of the Angular framework.
So we wait until the import completes and then pretend that the window `load` event fired again, causing Jasmine to start again, this time with our imported test queued up.
## Whats Next?
We are able to test a part of our application with simple Jasmine tests. That part was a stand-alone class that made no mention or use of Angular.
Thats not rare but its not typical either. Most of our application parts make some use of the Angular framework.
In the next chapter, well look at a class that does rely on Angular.
In the next chapter, well test a class that does rely on Angular.

View File

@ -1,458 +0,0 @@
include ../../../../_includes/_util-fns
:markdown
Let's start from zero and build a super simple Angular 2 application in TypeScript.
.callout.is-helpful
header Don't want TypeScript?
:markdown
Although we're getting started in TypeScript, you can also write Angular 2 apps
in JavaScript and Dart by selecting either of those languages from the combo-box in the banner.
.l-main-section
:markdown
# The shortest, quickest ...
Let's put something on the screen in Angular 2 as quickly as we can.
.l-sub-section
:markdown
While we are about to describe steps to take on your development machine,
you could take these same steps in an interactive, online coding environment
such as [plunker](http://plnkr.co/ "Plunker"). You won't have to
install a static server to run the app there.
If you like what you see - and we think you will - you can repeat this
exercise on your own machine later.
:markdown
**Create a new folder** to hold our application project, perhaps like this:
```
mkdir angular2-getting-started
cd angular2-getting-started
```
## Our first Angular component
**Add a new file** called **`app.ts`** and paste the following lines:
+makeExample('gettingstarted/ts/src/app/app.ts', null, 'app.ts')
:markdown
We've just defined an Angular 2 **component**,
one of the most important Angular 2 features.
Components are our primary means of creating application views
and supporting them with application logic.
Ours is an empty, do-nothing class class named `AppComponent`.
It would expand with properties and application
logic when we're ready to build a substantive application.
Above the class we see the `@Component` decoration.
.l-sub-section
:markdown
The `@` symbol before the method name identifies `Component` as a decoration.
A "decoration" is a TypeScript language feature
for creating metadata about the class. Angular finds this metadata
in the transpiled JavaScript and responds appropriately.
:markdown
`@Component` tells Angular that this class *is an Angular component*.
The configuration object passed to the `@Component` method has two
field, a `selector` and a `template`.
The `selector` specifies a CSS selector for a custom HTML element named `my-app`.
Angular creates and displays an instance of our `AppComponent`
wherever it encounters a `my-app` element.
The `template` field is the component's companion template
that tells Angular how to render a view.
Our template is a single line of HTML announcing "My First Angular App".
The `bootstrap` method tells Angular to start the application with this
component at the application root.
We'd be correct to guess that someday our application will
consist of more components arising in tree-like fashion from this root.
In the top line we imported the `Component`, `View`, and `bootstrap` methods
from the Angular 2 library. That's the way we do things now.
We no longer expect to find our code or any library code in a global namespace.
We `import` exactly what we need, as we need it, from named file and library resources.
## Add `index.html`
**Create** an `index.html` file.
**Paste** the following lines into it ... and we'll discuss them:
+makeExample('gettingstarted/ts/src/index.1.html', null, 'index.html')
:markdown
We see three noteworthy sections of HTML:
1. We load JavaScript libraries from the web.
Let's take them on faith without further discussion.<br/><br/>
2. We configure something called `System` and ask it to import the
application file with our `AppComponent` that we just wrote.
`System` is the module loader (from the `system.js` library),
a tool that can `import` code;
remember the `import` statement in our `AppComponent`?
We're also asking `system.js` to "transpile" (AKA "compile") our
TypeScript source code into JavaScript ... right here in the browser.<br/><br/>
3. We note the `<my-app>` tag in the `<body>`.
That's the custom HTML element we identified in the `@Component` decoration
adorning our `AppComponent` class.
## Run it!
We need a static file server to serve our application to the browser.
.l-sub-section
:markdown
Don't have a static file server handy? Let's install one of our favorites
called [live-server](https://www.npmjs.com/package/live-server "Live-server").
We'll use the **npm package manager** to install it. Don't have npm?
[Go get it](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
because we're going to use it now and repeatedly throughout the guide.
Once you have `npm` installed, open a terminal window and enter
pre.prettyprint.lang-bash
code npm install -g live-server
:markdown
Open a terminal window and enter
pre.prettyprint.lang-bash
code live-server
:markdown
In a few moments, a browser tab should open and display
figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
:markdown
Congratulations! We are in business.
.l-main-section
:markdown
## What's wrong with this?
We were up and running in a hurry and we could explore Angular
in this manner for quite some time.
For a number of reasons this isn't a good approach for building an application.
<!-- TODO The formatting here is a little weird. Should improve readability. -->
* Transpiling TypeScript in the browser becomes tediously slow when our
app grows beyond a few files. We certainly won't do that in production. We should learn to
compile locally and push the generated JavaScript to the server. We'll need some tools for that.
* Downloading JavaScript libraries from the web is OK for demos but
it slows our development. Every time our app reloads, it must refetch these libraries.
Don't count on browser caching.
Our debugging and live-reload techniques will bust the browser cache. Loading libraries
from the web also prevents us from developing our application offline or where connectivity is
poor. Let's learn to download the libraries to our machine and serve them locally.
* We want our development cycle to be as fast and friction-free as possible.
When we change our code, we want to see the results in the browser immediately.
We have tools and procedures for that.
.l-main-section
:markdown
# Upping our game
Let's take a few more steps to put our development on a better foundation. We will
1. Revise the application project structure for future growth
1. Install a few tools and packages
1. Revise the **`index.html`** to use local library resources
1. Compile the TypeScript locally and watch for changes
Shut down the `live-server` running in the terminal window (Ctrl-C) and proceed as follows.
.l-main-section
:markdown
## Revise the application project structure
At the moment we're dumping everything into the "angular2-getting-started" **root folder**.
Not bad when there are only two files. Not good as our application evolves.
Let's give our project a little structure.
We'll add a sub-folder - `src` - to hold project source code and a sub-sub-folder - `src/app` -
to hold the application source code.
In OS/X and Linux:
pre.prettyprint.lang-bash
code mkdir src/app
:markdown
In Windows:
pre.prettyprint.lang-bash
code mkdir src\app
:markdown
**Move `index.html`** into the **`src`** folder.
**Move `app.ts`** into the **`src/app`** folder.
Our project folders should look like this.
```
angular2-getting-started
└── src
├── app
│ └── app.ts
└── index.html
```
.l-main-section
:markdown
## Install npm packages locally
We'll replace the web-based scripts in our `index.html` with
scripts resident on our local machine.
We get those scripts by installing two runtime `npm` packages into our project.
>**angular.js** - the Angular 2 library.
>**system.js** - an open-source library that provides module loading.
We'll also install two development tools:
>**typescript** - the TypeScript compiler
>**[live-server](https://www.npmjs.com/package/live-server "Live-server")** - the static file server that reloads the browser when files change.
We may have loaded it earlier. We're doing it again
locally in our project so we are no longer vulnerable to
a global uninstall or version change.
**Open** a terminal window at our application's **root folder**
Enter these commands:
```
npm init -y
npm i angular2@2.0.0-alpha.42 systemjs@0.19.2 --save --save-exact
npm i typescript live-server --save-dev
```
These commands both *install* the packages and *create* an npm `package.json` that will
help us develop and maintain our application in future.
The essence of our `package.json` should look like this:
+makeJson('gettingstarted/ts/package.json', { paths: 'name, version, dependencies, devDependencies'})
:markdown
There is also a `scripts` section. **Find and replace** it with the following:
+makeJson('gettingstarted/ts/package.json', { paths: 'scripts'})
:markdown
We've just extended our project world with script commands
that we'll be running very soon.
.l-main-section
:markdown
## Update `index.html`
**Replace** the library scripts section with references to
scripts in the packages we just installed.
+makeExample('gettingstarted/ts/src/index.html', 'libraries')
:markdown
**Update** the `System` configuration script as follows.
+makeExample('gettingstarted/ts/src/index.html', 'systemjs')
.l-sub-section
:markdown
We won't be transpiling TypeScript in the browser anymore.
We'll do that on our machine and ship the generated JavaScript
files to the server.
We have to re-configure `system.js` to expect JavaScript files
with a `.js` extension by default.
Someday we might add a `Foo` class to our application in a `foo.ts`
file and import it like this
pre.prettyprint.lang-bash
code import {Foo} from './app/foo'
:markdown
`system.js`will know to look for a file named `foo.js` in the `src/app` folder.
That's exactly what we're doing in the last line. We're
importing our main application file `app` (the generated `app.js` to be precise)
from the `src/app/` folder (we moved it there, remember?)
:markdown
Here's the final version
+makeExample('gettingstarted/ts/src/index.html', null, 'index.html')
.l-main-section
:markdown
## Prepare for TypeScript Compilation
### Add the TypeScript configuration file
We'll add a configuration file named **`tsconfig.json`**
to tell the editor how to interpret our TypeScript code and
to simplify the TypeScript compilation command that we'll run very soon.
**Change to the `src` folder and create a `tsconfig.json`** file with the following content:
+makeJson('gettingstarted/ts/src/tsconfig.json', null, 'tsconfig.json')
.alert.is-helpful
:markdown
See the [TypeScript configuration appendix](#tsconfig) to learn more about
this file and these settings.
.l-main-section
:markdown
## Final structure
Our final project folder structure should look like this:
```
angular2-getting-started
├── node_modules
├── src
│ ├── app
| │ └── app.ts
│ ├── index.html
│ └── tsconfig.json
└── package.json
```
.l-main-section
:markdown
## Compile the TypeScript to JavaScript
We no longer transpile TypeScript to JavaScript in the browser.
We run the **T**ype**S**cript **C**ompiler (TSC) on our machine instead.
Open a terminal window in the **root of the application folder** and enter:
pre.prettyprint.lang-bash
code npm run tsc
:markdown
When it's done we should find the generated *app.js* file in the *src* folder and also an *app.map.js* file that
helps debuggers navigate between the JavaScript and the TypeScript source.
Our script set the compiler watch option (`-w`) so the
compiler stays alive when it's finished.
It watches for changes to our **`.ts`** files
and recompiles them automatically.
Leave this command running in the terminal window.
You can stop it anytime with `Ctrl-C`.
.l-main-section
:markdown
## Run the app!
Now we are ready to see our app in action.
Open another terminal window in the **root of the application folder** and
launch `live-server` again although this time we'll do it with
one of our `npm` script commands:
pre.prettyprint.lang-bash
code npm start
:markdown
**live-server** loads the browser for us, serves the HTML and JavaScript files,
and displays our application message once more:
figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
:markdown
### Make some changes
**`live-server`** detects changes to our files and refreshes the browser page for us automatically.
Try changing the message to "My SECOND Angular 2 app".
The TypeScript compiler in the first terminal window is watching our source code. It recompiles and produces
the revised *app.js*. The `live-server` sees that change and reloads the browser.
Keep `live-server` running in this terminal window. You can stop it anytime with `Ctrl-C`.
.l-main-section
:markdown
## What have we done?
Our first application doesn't do much. It's basically "Hello, World" for Angular 2.
We kept it simple in our first pass: we wrote a little Angular component,
we added some JavaScript libraries to `index.html`, and launched with a
static file server. That's about all we'd expect to do for a "Hello, World" app.
**We have greater ambitions.**
We won't ask Angular to build "Hello, World".
We are asking it to help us build sophisticated applications with sophisticated requirements.
So we made some strategic technology investments to reach our larger goals
* our application loads faster with libraries installed locally and
we can develop offline if we wish.
* we're pre-compiling our TypeScript.
* we're running the compiler and live-server with commands that give us immediate feedback as we make changes.
The good news is that the overhead of setup is (mostly) behind us.
We're about to build a small application that demonstrates the great things
we can build with Angular 2.
<!--TODO: Join us on the [Tour of Heroes](./toh-pt1) -->
<!-- Move this to the Style Guide when we have one -->
.l-main-section
:markdown
<a id="tsconfig"></a>
### Appendix: TypeScript configuration
We added a TypeScript configuration file (`tsconfig.js`) to our project to
guide the compiler as it generates JavaScript files.
Get details about `tsconfig.js` from the official
[TypeScript wiki](https://github.com/Microsoft/TypeScript/wiki/tsconfig.json).
We'd like a moment to discuss the `noImplicitAny` flag.
TypeScript developers disagree about whether it should be `true` or `false`.
There is no correct answer and we can change the flag later.
But our choice now can make a difference in larger projects so it merits
discussion.
When the `noImplicitAny` flag is `false`,
the compiler silently defaults the type of a variable to `any` if it cannot infer
the type based on how the variable is used. That's what we mean by "implicitly `any`".
When the `noImplicitAny` flag is `true` and the TypeScript compiler cannot infer
the type, it still generates the JavaScript files but
it also reports an error.
For this project and the other examples in this Developer Guide
we set the `noImplicitAny` flag to `false`.
Developers who prefer stricter type checking should set the `noImplicitAny` flag to `true`.
We can still set a variable's type to `any` if
that seems like the best choice. We'd be doing so explicitly after
giving the matter some thought.
If we set the `noImplicitAny` flag to `true`, we may get implicit index errors as well.
If we feel these are more annoying than helpful,
we can suppress them with the following additional flag.
```
"suppressImplicitAnyIndexErrors":true
```

View File

@ -1,7 +1,8 @@
include ../../../../_includes/_util-fns
:markdown
Well write our tests with the [Jasmine test framework](http://jasmine.github.io/2.3/introduction.html). Well start by getting *some* tests to work - *any* tests at all.
Well write our tests with the [Jasmine test framework](http://jasmine.github.io/2.3/introduction.html).
Well start by getting *some* tests to work - *any* tests at all.
We will learn
- basic Jasmine testing skills
@ -14,7 +15,8 @@ include ../../../../_includes/_util-fns
:markdown
## Install npm packages locally
Next follow all of the steps prescribed in “Install npm packages locally” in the [Getting Started](./gettingStarted.html) chapter.
Next follow all of the steps prescribed in “Install npm packages locally” of the
[QuickStart](../quickstart.html).
Well also add the Jasmine package via `npm`:
@ -39,13 +41,13 @@ pre.prettyprint.lang-bash
Create a new file called`unit-tests.html` and enter the following:
```
<html>
<head>
<title>1st Jasmine Tests</title>
<link rel="stylesheet" href="../node_modules/jasmine/lib/jasmine.css">
<script src="../node_modules/jasmine/lib/jasmine.js"></script>
<script src="../node_modules/jasmine/lib/jasmine-html.js"></script>
<script src="../node_modules/jasmine/lib/boot.js"></script>
</head>
<body>
@ -58,11 +60,11 @@ pre.prettyprint.lang-bash
Well write our first test with inline JavaScript inside the body tag:
```
<script>
it('true is true', function(){ expect(true).toEqual(true); });
</script>
```
```
<script>
it('true is true', function(){ expect(true).toEqual(true); });
</script>
```
Now open `unit-tests.html` in a browser and see the Jasmine HTML test output:
@ -73,7 +75,8 @@ figure.image-display
It doesnt get much simpler than that!
## First TypeScript Test
Perhaps too simple. We wont write our entire test suite inside one HTML file. Lets **extract** that line of test code to a **new file in `src` called `1st.spec.ts` ** .
Perhaps too simple. We wont write our entire test suite inside one HTML file.
Lets **extract** that line of test code to a **new file in `src` called `1st.spec.ts` ** .
.l-sub-section
:markdown
@ -82,22 +85,24 @@ figure.image-display
.l-main-section
:markdown
The test we wrote is valid TypeScript because any JavaScript is valid TypeScript. But lets make it more modern with an arrow function:
it('true is true', () => expect(true).toEqual(true));
```
it('true is true', () => expect(true).toEqual(true));
```
Now modify `unit-tests.html` to load the script:
<script src="1st.spec.js"></script>
```
<script src="1st.spec.js"></script>
```
Hold on! We wrote a TypeScript file but were loading a JavaScript file?
Thats a reminder that we need to compile our TypeScript test files as we do our TypeScript application files. Do that next.
## Prepare for TypeScript
As weve seen before, we first have to tell the compiler how to compile our TypeScript files with a ** `tsconfig.json` **.
As weve seen before, we first have to tell the compiler how to compile our TypeScript files with
a ** `tsconfig.json` **.
We can copy one from an application we wrote previously and paste it into our src sub-folder. It should look like this:
We can copy one from an application we wrote previously and paste it into our src sub-folder.
It should look something like this:
```
{
@ -110,20 +115,6 @@ figure.image-display
}
}
```
### Add *typings* (d.ts) files
Our editor may complain that it doesnt know what `it` and `expect` are because it lacks the typing files that describe Jasmine. Lets take care of that annoyance right now by creating a `tsd.json` file and asking `tsd` to fetch the Jasmine typings file.
Open a terminal window and enter:
```
tsd init
tsd install jasmine --save
```
.alert.is-helpful
You may have to reload your editor to see the typings files take effect.
:markdown
## Compile and Run
Compile in the terminal window using the npm script command
@ -131,10 +122,16 @@ figure.image-display
pre.prettyprint.lang-bash
code npm run tsc
.alert.is-helpful
:markdown
Our editor and the compiler may complain that they dont know
what `it` and `expect` are because they lack the typing files that describe Jasmine.
We can ignore those annoying complaints for now as they are harmless.
:markdown
If we reload the browser, we should see the same Jasmine test-runner output as before.
But well be evolving these tests rapidly and it would be nice to have the browser refresh automatically as we make changes and recompile.
Well be evolving these tests rapidly and it would be nice to have the browser refresh automatically as we make changes and recompile.
Lets launch with **live-server** in a second terminal window:
@ -152,14 +149,14 @@ pre.prettyprint.lang-bash
We should wrap this test something that identifies the file. In Jasmine that “something” is a `describe` function. Every test file should have at least one `describe` that identifies the file holding the test(s).
Heres what our revised`1st.spec.ts` looks like when wrapped in a `describe`:
Heres what our revised `1st.spec.ts` looks like when wrapped in a `describe`:
```
describe('1st tests', () => {
describe('1st tests', () => {
it('true is true', () => expect(true).toEqual(true));
});
it('true is true', () => expect(true).toEqual(true));
});
```
And heres how the test report displays it.
figure.image-display
@ -167,11 +164,11 @@ figure.image-display
:markdown
Lets add another Jasmine test to `1st.spec.ts`
it('null is not the same thing as undefined',
() => expect(null).not.toEqual(undefined)
);
```
it('null is not the same thing as undefined',
() => expect(null).not.toEqual(undefined)
);
```
You knew that right? Lets prove it with this test. The browser should refresh after you paste that test, and show:
figure.image-display

View File

@ -1,148 +1,164 @@
include ../../../../_includes/_util-fns
:markdown
Well test an Angular pipe in this chapter
Well test an Angular pipe in this chapter
An Angular pipe is a declarative way in HTML to transform some input into some displayable output.
An Angular pipe is a declarative way in HTML to transform some input into some displayable output.
Well look at our apps custom `InitCapsPipe` that converts a string of words into a string of capitalized words.
Well look at our apps custom `InitCapsPipe` that converts a string of words into a string of capitalized words.
We use it our `hero-detail.component.html` template to turn a hero name like “eeny weenie” into “Eeny Weenie”
We use it our `hero-detail.component.html` template to turn a hero name like “eeny weenie” into “Eeny Weenie”
The code for `InitCapsPipe` in `init-caps-pipe.ts` is quite brief:
code-example(format="linenums").
&lt;h2&gt;{{hero.name | initCaps}} is {{userName}}'s current super hero!&lt;/h2&gt;
&lt;h2&gt;{{hero.name | initCaps}} is {{userName}}'s current super hero!&lt;/h2&gt;
:markdown
The code for `InitCapsPipe` in `init-caps-pipe.ts` is quite brief:
The code for `InitCapsPipe` in `init-caps-pipe.ts` is quite brief:
```
import {Pipe} from 'angular2/angular2';
```
import {Pipe} from 'angular2/angular2';
@Pipe({ name: 'initCaps' })
export class InitCapsPipe {
transform(value: string) {
return value.toLowerCase().replace(/(?:^|\s)[a-z]/g, function(m) {
return m.toUpperCase();
});
}
}
```
@Pipe({ name: 'initCaps' })
export class InitCapsPipe {
transform(value: string) {
return value.toLowerCase().replace(/(?:^|\s)[a-z]/g, function(m) {
return m.toUpperCase();
});
}
}
```
In this chapter we will:
- add the Angular 2 library to our test harness
- test this custom Angular pipe class
- load multiple test files in our test harness, using system.js
In this chapter we will:
- add the Angular 2 library to our test harness
- test this custom Angular pipe class
- load multiple test files in our test harness, using system.js
.callout.is-helpful
header Prior Knowledge
p This chapter assumes familiarity with basic Angular 2 concepts, the tools we introduced in <a href="./gettingStarted.html">Getting Started</a> and <a href="./toh-pt1.html">Tour of Heroes</a>, and earlier chapters of this Unit Testing series.
header Prior Knowledge
:markdown
The Unit Testing chapters build upon each other. We recommend reading them in order.
We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools
we introduced in the [QuickStart](../quickstart.html) and
the [Tour of Heroes](./toh-pt1.html) tutorial
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
:markdown
## Add the Angular library
Looking back at `unit-tests.html` we realize that we have not loaded the Angular library. Yet we were able to load and test the applications `Hero` class.
## Add the Angular library
Looking back at `unit-tests.html` we realize that we have not loaded the Angular library.
Yet we were able to load and test the applications `Hero` class.
**We were lucky!** The `Hero` class has no dependence on Angular. If it had depended on Angular, wed still be staring at the Jasmine “big-time fail” screen:
**We were lucky!** The `Hero` class has no dependence on Angular.
If it had depended on Angular, wed still be staring at the Jasmine “big-time fail” screen:
figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png' style="width:400px;" alt="Jasmine's' big time fail screen")
img(src='/resources/images/devguide/testing-an-angular-pipe/big-time-fail-screen.png'
style="width:400px;" alt="Jasmine's' big time fail screen")
:markdown
If we then opened the browsers Developer Tools (F12, Ctrl-Shift-I) and looked in the console window, we would see.
If we then opened the browsers Developer Tools (F12, Ctrl-Shift-I) and looked
in the console window, we would see that SystemJS
tried to load Angular and couldn't find it.
`GET http://127.0.0.1:8080/src/angular2/angular2 404 (Not Found)` <!--TODO probably belongs
in a code box not as an inline code style -->
```
GET http://127.0.0.1:8080/src/angular2/angular2 404 (Not Found)
```
We are writing an Angular application afterall and
we were going to need Angular sooner or later. That time has come.
The `InitCapsPiep` clearly depends on Angular as is clear in the first few lines:
```
import {Pipe} from 'angular2/angular2';
It is missing indeed!
@Pipe({ name: 'initCaps' })
export class InitCapsPipe {
```
**Open** `unit-tests.html`
We are going to need Angular sooner or later. We are writing an Angular application and we expect to use it at some point.
**Find** the `src="../node_modules/systemjs/dist/system.src.js"></script>`
That moment has arrived! The `InitCapsPiep` clearly depends on Angular. That much is clear in the first few lines:
**Replace** Step #1 with these two scripts:
```
<!-- #1. add the system.js and angular libraries -->
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
```
## Add another spec file
import {Pipe} from 'angular2/angular2';
**Create** an *`init-caps-pipe.spec.ts`** next to `init-caps-pipes.ts` in `src/app`
@Pipe({ name: 'initCaps' })
export class InitCapsPipe {
**Stop and restart the TypeScript compiler** to ensure we compile the new file.
Lets not wait for trouble. Load the Angular library now… along with its essential companion, the `traceur-runtime`.
**Add** the following lines of rather obvious Jasmine test code
```
import {InitCapsPipe} from './init-caps-pipe';
**Open** `unit-tests.html`
describe('InitCapsPipe', () => {
let pipe:InitCapsPipe;
**Find** the `src="../node_modules/systemjs/dist/system.src.js"></script>`
beforeEach(() => {
pipe = new InitCapsPipe();
});
**Replace** Step #1 with these two scripts:
it('transforms "abc" to "Abc"', () => {
expect(pipe.transform('abc')).toEqual('Abc');
});
<!-- #1. add the system.js and angular libraries -->
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
it('transforms "abc def" to "Abc Def"', () => {
expect(pipe.transform('abc def')).toEqual('Abc Def');
});
## Add another spec file
it('leaves "Abc Def" unchanged', () => {
expect(pipe.transform('Abc Def')).toEqual('Abc Def');
});
});
```
Note that each test is short (one line in our case).
It has a clear label that accurately describes the test. And it makes exactly one expectation.
**Create** an ** `init-caps-pipe.spec.ts` ** next to `init-caps-pipes.ts` in `src/app`
Anyone can read these tests and understand quickly what the test does and what the pipe does.
If one of the tests fails, we know which expected behavior is no longer true.
Well have little trouble maintaining these tests and adding more like them as we encounter new conditions to explore.
**Stop and restart the TypeScript compiler** to ensure we compile the new file.
Thats the way we like our tests!
**Add** the following lines of unremarkable Jasmine test code
## Add this spec to `unit-tests.html`
import {InitCapsPipe} from './init-caps-pipe';
Now lets wire our new spec file into the HTML test harness.
describe('InitCapsPipe', () => {
let pipe:InitCapsPipe;
Open `unit-tests.html`. Find `System.import('app/hero.spec')`.
beforeEach(() => {
pipe = new InitCapsPipe();
});
Hmm. We cant just add `System.import('app/init-caps-pipe.spec')`.
it('transforms "abc" to "Abc"', () => {
expect(pipe.transform('abc')).toEqual('Abc');
});
The first `System.import` returns a promise as does this second import.
We cant run any of the Jasmine tests until **both imports are finished**.
it('transforms "abc def" to "Abc Def"', () => {
expect(pipe.transform('abc def')).toEqual('Abc Def');
});
it('leaves "Abc Def" unchanged', () => {
expect(pipe.transform('Abc Def')).toEqual('Abc Def');
});
});
Note that each test is short (one line in our case). It has a clear label that accurately describes the test. And it makes exactly one expectation.
Anyone can read these tests and understand quickly what the test does and what the pipe does. If one of the tests fails, we know which expected behavior is no longer true. Well have little trouble maintaining these tests and adding more like them as we encounter new conditions to explore.
Thats the way we like our tests!
## Add this spec to `unit-tests.html`
Now lets wire our new spec file into the HTML test harness.
Open `unit-tests.html`. Find `System.import('app/hero.spec')`.
Hmm. We cant just add `System.import('app/init-caps-pipe.spec')`.
The first `System.import` returns a promise as does this second import. We cant run any of the Jasmine tests until **both imports are finished**.
Fortunately, we can create a new `Promise` that wraps both import promises and waits for both to finish loading.
// #3. Import the spec files explicitly
Promise.all([
System.import('app/hero.spec'),
System.import('app/init-caps-pipe.spec')
])
Try it. The browser should refresh and show
Fortunately, we can create a new `Promise` that wraps both import promises and waits
for both to finish loading.
```
// #3. Import the spec files explicitly
Promise.all([
System.import('app/hero.spec'),
System.import('app/init-caps-pipe.spec')
])
```
Try it. The browser should refresh and show
figure.image-display
img(src='/resources/images/devguide/testing-an-angular-pipe/5-specs-0-failures.png' style="width:400px;" alt="import promises 5 specs, 0 failures")
img(src='/resources/images/devguide/testing-an-angular-pipe/5-specs-0-failures.png'
style="width:400px;" alt="import promises 5 specs, 0 failures")
:markdown
We have a pattern for adding new tests.
We have a pattern for adding new tests.
In future, when we add a new spec, we add another `System.import('app/some.spec')` to the array argument passed to `Promise.all`.
In future, when we add a new spec, we add another `System.import('app/some.spec')` to
the array argument passed to `Promise.all`.
## Whats Next?
## Whats Next?
Now we can test parts of our application that we *load* asynchronously with system.js.
Now we can test parts of our application that we *load* asynchronously with system.js.
What about testing parts that *are themselves asynchronous*?
What about testing parts that *are themselves asynchronous*?
In the next chapter well test a service with a public asynchronous method that fetches heroes from a remote server.
In the next chapter well test a service with a public asynchronous method that fetches heroes
from a remote server.

View File

@ -63,12 +63,12 @@ include ../../../../_includes/_util-fns
:markdown
# Once Upon a Time
Every story starts somewhere. Our story starts where the [Getting Started chapter]('./gettingstarted') ends.
Every story starts somewhere. Our story starts where the [QuickStart](../quickstart) ends.
Follow the "Getting Started" steps. They provide the prerequisites, the folder structure,
Follow the "QuickStart" steps. They provide the prerequisites, the folder structure,
and the core files for our Tour of Heroes.
Copy the "Getting Started" code to a new folder and rename the folder `angular2-tour-of-heroes`.
Copy the "QuickStart" code to a new folder and rename the folder `angular2-tour-of-heroes`.
We should have the following structure:
code-example.

View File

@ -113,7 +113,12 @@ figure.image-display
.callout.is-helpful
header How to Use This Guide
p The three Unit Testing chapters build upon each other. We recommend reading them in order. We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools we introduced in <a href="./gettingStarted.html">Getting Started</a> and <a href="./toh-pt1.html">Tour of Heroes</a> such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
:markdown
The Unit Testing chapters build upon each other. We recommend reading them in order.
We're also assuming that you're already comfortable with basic Angular 2 concepts and the tools
we introduced in the [QuickStart](../quickstart.html) and
the [Tour of Heroes](./toh-pt1.html) tutorial
such as <code>npm</code>, <code>gulp</code>, and <code>live-server</code>.
:markdown
Lets get started!

View File

@ -0,0 +1,260 @@
.callout.is-helpful
header Angular is in developer preview
p.
This quickstart does not reflect the final development process for writing apps with Angular.
The following setup is for those who want to try out Angular while it is in developer preview.
// STEP 1 - Create a project ##########################
.l-main-section
h2#section-create-project 1. Create a project
p.
This quickstart shows how to write your Angular components in TypeScript. You could instead choose
another language such as <a href="/docs/dart/latest/quickstart.html">Dart</a>, ES5, or ES6.
p.
The goal of this quickstart is to write a component in TypeScript that prints a string.
We assume you have already installed <a href="https://docs.npmjs.com/getting-started/installing-node">Node and npm</a>.
p.
To get started, create a new empty project directory. All the following commands should be run
from this directory.
p.
To get the benefits of TypeScript, we want to have the type definitions available for the compiler and the editor.
TypeScript type definitions are typically published in a repo called <a href="http://definitelytyped.org/">DefinitelyTyped</a>.
To fetch one of the type definitions to the local directory, we use the <a href="https://www.npmjs.com/package/tsd">tsd package manager</a>.
code-example.
$ npm install -g tsd@^0.6.0
$ tsd install angular2 es6-promise rx rx-lite
p.
Next, create two empty files, <code>index.html</code> and <code>app.ts</code>, both at the root of the project:
code-example.
$ touch app.ts index.html
// STEP 2 - Start the TypeScript compiler ##########################
.l-main-section
h2#start-tsc 2. Run the TypeScript compiler
p.
Since the browser doesn't understand TypeScript code, we need to run a compiler to translate
your code to browser-compliant JavaScript as you work. This quickstart uses the TypeScript
compiler in <code>--watch</code> mode, but it is also possible to do the translation in the browser as files
are loaded, or configure your editor or IDE to do it.
code-example.
$ npm install -g typescript@^1.5.0-beta
$ tsc --watch -m commonjs -t es5 --emitDecoratorMetadata app.ts
.callout.is-helpful
p.
Windows users: if you get an error that an option is unknown, you are probably running
an older version of TypeScript.
See <a href="http://stackoverflow.com/questions/23267858/how-do-i-install-typescript">
Stack Overflow: How do I install Typescript</a>
// STEP 3 - Import Angular ##########################
.l-main-section
h2#section-transpile 3. Import Angular
p Inside of <code>app.ts</code>, import the type definitions from Angular:
code-example.
/// &lt;reference path="typings/angular2/angular2.d.ts" /&gt;
p Now your editor should be able to complete the available imports:
code-example.
import {Component, View, bootstrap} from 'angular2/angular2';
p.
The above import statement uses ES6 module syntax to import three symbols from the Angular module.
The module will load at runtime.
// STEP 4 - Create a component ##########################
.l-main-section
h2#section-angular-create-account 4. Define a component
p.
Components structure and represent the UI. This quickstart demonstrates the process of creating a component
that has an HTML tag named <strong><code>&lt;my-app&gt;</code></strong>.
p.
A component consists of two parts, the <strong>component controller</strong>
which is an ES6 class, and the <strong>decorators</strong> which tell Angular
how to place the component into the page.
code-example(language="javascript" format="linenums").
// Annotation section
@Component({
selector: 'my-app'
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;'
})
// Component controller
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
.l-sub-section
h3 @Component and @View annotations
p.
A component annotation describes details about the component. An annotation can be identified by its at-sign (<code>@</code>).
p.
The <code>@Component</code> annotation defines the HTML tag for the component by specifying the component's CSS selector.
p.
The <code>@View</code> annotation defines the HTML that represents the component. The component you wrote uses an inline template, but you can also have an external template. To use an external template, specify a <code>templateUrl</code> property and give it the path to the HTML file.
code-example(language="javascript" format="linenums").
@Component({
selector: 'my-app' // Defines the &lt;my-app&gt;&lt;/my-app&gt; tag
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;' // Defines the inline template for the component
})
p.
The annotations above specify an HTML tag of <code>&lt;my-app&gt;</code>
and a template of <code ng-non-bindable>&lt;h1&gt;Hello &#123;&#123; name }}&lt;/h1&gt;</code>.
.l-sub-section
h3 The template and the component controller
p.
The component controller is the backing of the component's template. This component
controller uses TypeScript <code>class</code> syntax.
code-example(language="javascript" format="linenums").
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
p.
Templates read from their component controllers. Templates have access to any properties
or functions placed on the component controller.
p.
The template above binds to a <code>name</code> property through
the double-mustache syntax (<code ng-non-bindable>{{ ... }}</code>).
The body of the constructor assigns "Alice" to the name property. When the
template renders, "Hello Alice" appears instead of
<span ng-non-bindable>"Hello {{ name }}"</span>.
// STEP 5 - Bootstrap ##########################
.l-main-section
h2#section-transpile 5. Bootstrap
p.
At the bottom of <code>app.ts</code>, call the <code>bootstrap()</code> function
to load your new component into its page:
code-example(language="javaScript").
bootstrap(MyAppComponent);
p.
The <code>bootstrap()</code> function takes a
component as a parameter, enabling the component
(as well as any child components it contains) to render.
// STEP 6 - Declare the HTML ##########################
.l-main-section
h2#section-angular-create-account 6. Declare the HTML
p.
Inside the <code>head</code> tag of <code>index.html</code>,
include the traceur-runtime and the Angular bundle.
Instantiate the <code>my-app</code> component in the <code>body</code>.
code-example(language="html" format="linenums").
&lt;!-- index.html --&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- The app component created in app.ts --&gt;
&lt;my-app&gt;&lt;/my-app&gt;
&lt;/body&gt;
&lt;/html&gt;
// STEP 7 - Declare the HTML ##########################
.l-main-section
h2#section-load-component-module 7. Load the component
p.
The last step is to load the module for the <code>my-app</code> component.
To do this, we'll use the System library.
.l-sub-section
h3 System.js
p.
<a href="https://github.com/systemjs/systemjs">System</a> is a third-party open-source library that
adds ES6 module loading functionality to browsers.
p.
Add the System.js dependency in the <code>&lt;head&gt;</code> tag, so that
it looks like:
code-example(language="html" format="linenums").
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://jspm.io/system@0.16.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
p.
Add the following module-loading code:
code-example(language="html" format="linenums").
&lt;my-app&gt;&lt;/my-app&gt;
&lt;script&gt;System.import('app');&lt;/script&gt;
// STEP 8 - Run a local server ##########################
.l-main-section
h2#section-load-component-module 8. Run a local server
p Run a local HTTP server, and view <code>index.html</code>.
p.
If you don't already have an HTTP server,
you can install one using <code>npm install -g http-server</code>.
(If that results in an access error, then you might need to use
<code><b>sudo</b> npm ...</code>)
For example:
code-example.
# From the directory that contains index.html:
npm install -g http-server # Or sudo npm install -g http-server
http-server # Creates a server at localhost:8080
# In a browser, visit localhost:8080/index.html
// WHAT'S NEXT... ##########################
.l-main-section
h2#section-transpile Great job! We'll have the next steps out soon.

View File

@ -1,260 +1,459 @@
.callout.is-helpful
header Angular is in developer preview
p.
This quickstart does not reflect the final development process for writing apps with Angular.
The following setup is for those who want to try out Angular while it is in developer preview.
include ../../../_includes/_util-fns
// STEP 1 - Create a project ##########################
.l-main-section
h2#section-create-project 1. Create a project
p.
This quickstart shows how to write your Angular components in TypeScript. You could instead choose
another language such as <a href="/docs/dart/latest/quickstart.html">Dart</a>, ES5, or ES6.
p.
The goal of this quickstart is to write a component in TypeScript that prints a string.
We assume you have already installed <a href="https://docs.npmjs.com/getting-started/installing-node">Node and npm</a>.
p.
To get started, create a new empty project directory. All the following commands should be run
from this directory.
p.
To get the benefits of TypeScript, we want to have the type definitions available for the compiler and the editor.
TypeScript type definitions are typically published in a repo called <a href="http://definitelytyped.org/">DefinitelyTyped</a>.
To fetch one of the type definitions to the local directory, we use the <a href="https://www.npmjs.com/package/tsd">tsd package manager</a>.
code-example.
$ npm install -g tsd@^0.6.0
$ tsd install angular2 es6-promise rx rx-lite
p.
Next, create two empty files, <code>index.html</code> and <code>app.ts</code>, both at the root of the project:
code-example.
$ touch app.ts index.html
// STEP 2 - Start the TypeScript compiler ##########################
.l-main-section
h2#start-tsc 2. Run the TypeScript compiler
p.
Since the browser doesn't understand TypeScript code, we need to run a compiler to translate
your code to browser-compliant JavaScript as you work. This quickstart uses the TypeScript
compiler in <code>--watch</code> mode, but it is also possible to do the translation in the browser as files
are loaded, or configure your editor or IDE to do it.
code-example.
$ npm install -g typescript@^1.5.0-beta
$ tsc --watch -m commonjs -t es5 --emitDecoratorMetadata app.ts
:markdown
Let's start from zero and build a super simple Angular 2 application in TypeScript.
.callout.is-helpful
p.
Windows users: if you get an error that an option is unknown, you are probably running
an older version of TypeScript.
See <a href="http://stackoverflow.com/questions/23267858/how-do-i-install-typescript">
Stack Overflow: How do I install Typescript</a>
header Don't want TypeScript?
:markdown
Although we're getting started in TypeScript, you can also write Angular 2 apps
in JavaScript and Dart by selecting either of those languages from the combo-box in the banner.
// STEP 3 - Import Angular ##########################
.l-main-section
h2#section-transpile 3. Import Angular
p Inside of <code>app.ts</code>, import the type definitions from Angular:
code-example.
/// &lt;reference path="typings/angular2/angular2.d.ts" /&gt;
p Now your editor should be able to complete the available imports:
code-example.
import {Component, View, bootstrap} from 'angular2/angular2';
p.
The above import statement uses ES6 module syntax to import three symbols from the Angular module.
The module will load at runtime.
// STEP 4 - Create a component ##########################
.l-main-section
h2#section-angular-create-account 4. Define a component
:markdown
# The shortest, quickest ...
p.
Components structure and represent the UI. This quickstart demonstrates the process of creating a component
that has an HTML tag named <strong><code>&lt;my-app&gt;</code></strong>.
p.
A component consists of two parts, the <strong>component controller</strong>
which is an ES6 class, and the <strong>decorators</strong> which tell Angular
how to place the component into the page.
code-example(language="javascript" format="linenums").
// Annotation section
@Component({
selector: 'my-app'
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;'
})
// Component controller
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
Let's put something on the screen in Angular 2 as quickly as we can.
.l-sub-section
h3 @Component and @View annotations
:markdown
While we are about to describe steps to take on your development machine,
you could take these same steps in an interactive, online coding environment
such as [plunker](http://plnkr.co/ "Plunker"). You won't have to
install a static server to run the app there.
p.
A component annotation describes details about the component. An annotation can be identified by its at-sign (<code>@</code>).
p.
The <code>@Component</code> annotation defines the HTML tag for the component by specifying the component's CSS selector.
p.
The <code>@View</code> annotation defines the HTML that represents the component. The component you wrote uses an inline template, but you can also have an external template. To use an external template, specify a <code>templateUrl</code> property and give it the path to the HTML file.
If you like what you see - and we think you will - you can repeat this
exercise on your own machine later.
code-example(language="javascript" format="linenums").
@Component({
selector: 'my-app' // Defines the &lt;my-app&gt;&lt;/my-app&gt; tag
})
@View({
template: '&lt;h1&gt;Hello {{ name }}&lt;/h1&gt;' // Defines the inline template for the component
})
:markdown
**Create a new folder** to hold our application project, perhaps like this:
```
mkdir angular2-getting-started
cd angular2-getting-started
```
p.
The annotations above specify an HTML tag of <code>&lt;my-app&gt;</code>
and a template of <code ng-non-bindable>&lt;h1&gt;Hello &#123;&#123; name }}&lt;/h1&gt;</code>.
## Our first Angular component
**Add a new file** called **`app.ts`** and paste the following lines:
+makeExample('gettingstarted/ts/src/app/app.ts', null, 'app.ts')
:markdown
We've just defined an Angular 2 **component**,
one of the most important Angular 2 features.
Components are our primary means of creating application views
and supporting them with application logic.
Ours is an empty, do-nothing class class named `AppComponent`.
It would expand with properties and application
logic when we're ready to build a substantive application.
Above the class we see the `@Component` decoration.
.l-sub-section
h3 The template and the component controller
:markdown
The `@` symbol before the method name identifies `Component` as a decoration.
A "decoration" is a TypeScript language feature
for creating metadata about the class. Angular finds this metadata
in the transpiled JavaScript and responds appropriately.
:markdown
`@Component` tells Angular that this class *is an Angular component*.
The configuration object passed to the `@Component` method has two
field, a `selector` and a `template`.
p.
The component controller is the backing of the component's template. This component
controller uses TypeScript <code>class</code> syntax.
The `selector` specifies a CSS selector for a host HTML element named `my-app`.
Angular creates and displays an instance of our `AppComponent`
wherever it encounters a `my-app` element.
code-example(language="javascript" format="linenums").
class MyAppComponent {
name: string;
constructor() {
this.name = 'Alice';
}
}
The `template` field is the component's companion template
that tells Angular how to render a view.
Our template is a single line of HTML announcing "My First Angular App".
p.
Templates read from their component controllers. Templates have access to any properties
or functions placed on the component controller.
The `bootstrap` method tells Angular to start the application with this
component at the application root.
We'd be correct to guess that someday our application will
consist of more components arising in tree-like fashion from this root.
p.
The template above binds to a <code>name</code> property through
the double-mustache syntax (<code ng-non-bindable>{{ ... }}</code>).
The body of the constructor assigns "Alice" to the name property. When the
template renders, "Hello Alice" appears instead of
<span ng-non-bindable>"Hello {{ name }}"</span>.
In the top line we imported the `Component`, `View`, and `bootstrap` methods
from the Angular 2 library. That's the way we do things now.
We no longer expect to find our code or any library code in a global namespace.
We `import` exactly what we need, as we need it, from named file and library resources.
## Add `index.html`
**Create** an `index.html` file.
// STEP 5 - Bootstrap ##########################
.l-main-section
h2#section-transpile 5. Bootstrap
**Paste** the following lines into it ... and we'll discuss them:
p.
At the bottom of <code>app.ts</code>, call the <code>bootstrap()</code> function
to load your new component into its page:
+makeExample('gettingstarted/ts/src/index.1.html', null, 'index.html')
code-example(language="javaScript").
bootstrap(MyAppComponent);
:markdown
We see three noteworthy sections of HTML:
1. We load JavaScript libraries from the web.
Let's take them on faith without further discussion.<br/><br/>
p.
The <code>bootstrap()</code> function takes a
component as a parameter, enabling the component
(as well as any child components it contains) to render.
2. We configure something called `System` and ask it to import the
application file with our `AppComponent` that we just wrote.
`System` is the module loader (from the `system.js` library),
a tool that can `import` code;
remember the `import` statement in our `AppComponent`?
We're also asking `system.js` to "transpile" (AKA "compile") our
TypeScript source code into JavaScript ... right here in the browser.<br/><br/>
// STEP 6 - Declare the HTML ##########################
.l-main-section
3. We note the `<my-app>` tag in the `<body>`.
That's the custom HTML element we identified in the `@Component` decoration
adorning our `AppComponent` class.
h2#section-angular-create-account 6. Declare the HTML
## Run it!
p.
Inside the <code>head</code> tag of <code>index.html</code>,
include the traceur-runtime and the Angular bundle.
Instantiate the <code>my-app</code> component in the <code>body</code>.
code-example(language="html" format="linenums").
&lt;!-- index.html --&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!-- The app component created in app.ts --&gt;
&lt;my-app&gt;&lt;/my-app&gt;
&lt;/body&gt;
&lt;/html&gt;
// STEP 7 - Declare the HTML ##########################
.l-main-section
h2#section-load-component-module 7. Load the component
p.
The last step is to load the module for the <code>my-app</code> component.
To do this, we'll use the System library.
We need a static file server to serve our application to the browser.
.l-sub-section
h3 System.js
:markdown
Don't have a static file server handy? Let's install one of our favorites
called [live-server](https://www.npmjs.com/package/live-server "Live-server")
with the **npm package manager**.
Don't have npm?
[Get it now](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
because we're going to use it now and repeatedly throughout this documentation.
p.
<a href="https://github.com/systemjs/systemjs">System</a> is a third-party open-source library that
adds ES6 module loading functionality to browsers.
Once you have `npm` installed, open a terminal window and enter
p.
Add the System.js dependency in the <code>&lt;head&gt;</code> tag, so that
it looks like:
pre.prettyprint.lang-bash
code npm install -g live-server
code-example(language="html" format="linenums").
&lt;head&gt;
&lt;title&gt;Angular 2 Quickstart&lt;/title&gt;
&lt;script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"&gt;&lt;/script&gt;
&lt;script src="https://jspm.io/system@0.16.js"&gt;&lt;/script&gt;
&lt;script src="https://code.angularjs.org/2.0.0-alpha.28/angular2.dev.js"&gt;&lt;/script&gt;
&lt;/head&gt;
:markdown
Open a terminal window and enter
p.
Add the following module-loading code:
pre.prettyprint.lang-bash
code live-server
:markdown
In a few moments, a browser tab should open and display
code-example(language="html" format="linenums").
&lt;my-app&gt;&lt;/my-app&gt;
&lt;script&gt;System.import('app');&lt;/script&gt;
figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
:markdown
Congratulations! We are in business.
// STEP 8 - Run a local server ##########################
.l-main-section
h2#section-load-component-module 8. Run a local server
:markdown
## What's wrong with this?
p Run a local HTTP server, and view <code>index.html</code>.
We were up and running in a hurry and we could explore Angular
in this manner for quite some time.
p.
If you don't already have an HTTP server,
you can install one using <code>npm install -g http-server</code>.
(If that results in an access error, then you might need to use
<code><b>sudo</b> npm ...</code>)
For example:
For a number of reasons this isn't a good approach for building an application.
<!-- TODO The formatting here is a little weird. Should improve readability. -->
code-example.
# From the directory that contains index.html:
npm install -g http-server # Or sudo npm install -g http-server
http-server # Creates a server at localhost:8080
# In a browser, visit localhost:8080/index.html
* Transpiling TypeScript in the browser becomes tediously slow when our
app grows beyond a few files. We certainly won't do that in production. We should learn to
compile locally and push the generated JavaScript to the server. We'll need some tools for that.
// WHAT'S NEXT... ##########################
* Downloading JavaScript libraries from the web is OK for demos but
it slows our development. Every time our app reloads, it must refetch these libraries.
Don't count on browser caching.
Our debugging and live-reload techniques will bust the browser cache. Loading libraries
from the web also prevents us from developing our application offline or where connectivity is
poor. Let's learn to download the libraries to our machine and serve them locally.
* We want our development cycle to be as fast and friction-free as possible.
When we change our code, we want to see the results in the browser immediately.
We have tools and procedures for that.
.l-main-section
h2#section-transpile Great job! We'll have the next steps out soon.
:markdown
# Upping our game
Let's take a few more steps to put our development on a better foundation. We will
1. Revise the application project structure for future growth
1. Install a few tools and packages
1. Revise the **`index.html`** to use local library resources
1. Compile the TypeScript locally and watch for changes
Shut down the `live-server` running in the terminal window (Ctrl-C) and proceed as follows.
.l-main-section
:markdown
## Revise the application project structure
At the moment we're dumping everything into the "angular2-getting-started" **root folder**.
Not bad when there are only two files. Not good as our application evolves.
Let's give our project a little structure.
We'll add a sub-folder - `src` - to hold project source code and a sub-sub-folder - `src/app` -
to hold the application source code.
In OS/X and Linux:
pre.prettyprint.lang-bash
code mkdir src/app
:markdown
In Windows:
pre.prettyprint.lang-bash
code mkdir src\app
:markdown
**Move `index.html`** into the **`src`** folder.
**Move `app.ts`** into the **`src/app`** folder.
Our project folders should look like this.
```
angular2-getting-started
└── src
├── app
│ └── app.ts
└── index.html
```
.l-main-section
:markdown
## Install npm packages locally
We'll replace the web-based scripts in our `index.html` with
scripts resident on our local machine.
We get those scripts by installing two runtime `npm` packages into our project.
>**angular2** - the Angular 2 library.
>**systemjs** - an open-source library that provides module loading.
We'll also install two development tools:
>**typescript** - the TypeScript compiler
>**[live-server](https://www.npmjs.com/package/live-server "Live-server")** - the static file server that reloads the browser when files change.
We may have loaded it earlier. We're doing it again
locally in our project so we are no longer vulnerable to
a global uninstall or version change.
**Open** a terminal window at our application's **root folder**
Enter these commands:
```
npm init -y
npm i angular2@2.0.0-alpha.42 systemjs@0.19.2 --save --save-exact
npm i typescript live-server --save-dev
```
These commands both *install* the packages and *create* an npm `package.json` that will
help us develop and maintain our application in future.
The essence of our `package.json` should look like this:
+makeJson('gettingstarted/ts/package.json', { paths: 'name, version, dependencies, devDependencies'})
:markdown
There is also a `scripts` section. **Find and replace** it with the following:
+makeJson('gettingstarted/ts/package.json', { paths: 'scripts'})
:markdown
We've just extended our project world with script commands
that we'll be running very soon.
.l-main-section
:markdown
## Update `index.html`
**Replace** the library scripts section with references to
scripts in the packages we just installed.
+makeExample('gettingstarted/ts/src/index.html', 'libraries')
:markdown
**Update** the `System` configuration script as follows.
+makeExample('gettingstarted/ts/src/index.html', 'systemjs')
.l-sub-section
:markdown
We won't be transpiling TypeScript in the browser anymore.
We'll do that on our machine and ship the generated JavaScript
files to the server.
We have to re-configure `system.js` to expect JavaScript files
with a `.js` extension by default.
Someday we might add a `Foo` class to our application in a `foo.ts`
file and import it like this
pre.prettyprint.lang-bash
code import {Foo} from './app/foo'
:markdown
`system.js`will know to look for a file named `foo.js` in the `src/app` folder.
That's exactly what we're doing in the last line. We're
importing our main application file `app` (the generated `app.js` to be precise)
from the `src/app/` folder (we moved it there, remember?)
:markdown
Here's the final version
+makeExample('gettingstarted/ts/src/index.html', null, 'index.html')
.l-main-section
:markdown
## Prepare for TypeScript Compilation
### Add the TypeScript configuration file
We'll add a configuration file named **`tsconfig.json`**
to tell the editor how to interpret our TypeScript code and
to simplify the TypeScript compilation command that we'll run very soon.
**Change to the `src` folder and create a `tsconfig.json`** file with the following content:
+makeJson('gettingstarted/ts/src/tsconfig.json', null, 'tsconfig.json')
.alert.is-helpful
:markdown
See the [TypeScript configuration appendix](#tsconfig) to learn more about
this file and these settings.
.l-main-section
:markdown
## Final structure
Our final project folder structure should look like this:
```
angular2-getting-started
├── node_modules
├── src
│ ├── app
| │ └── app.ts
│ ├── index.html
│ └── tsconfig.json
└── package.json
```
.l-main-section
:markdown
## Compile the TypeScript to JavaScript
We no longer transpile TypeScript to JavaScript in the browser.
We run the **T**ype**S**cript **C**ompiler (TSC) on our machine instead.
Open a terminal window in the **root of the application folder** and enter:
pre.prettyprint.lang-bash
code npm run tsc
:markdown
When it's done we should find the generated *app.js* file in the *src* folder and also an *app.map.js* file that
helps debuggers navigate between the JavaScript and the TypeScript source.
Our script set the compiler watch option (`-w`) so the
compiler stays alive when it's finished.
It watches for changes to our **`.ts`** files
and recompiles them automatically.
Leave this command running in the terminal window.
You can stop it anytime with `Ctrl-C`.
.l-main-section
:markdown
## Run the app!
Now we are ready to see our app in action.
Open another terminal window in the **root of the application folder** and
launch `live-server` again although this time we'll do it with
one of our `npm` script commands:
pre.prettyprint.lang-bash
code npm start
:markdown
**live-server** loads the browser for us, serves the HTML and JavaScript files,
and displays our application message once more:
figure.image-display
img(src='/resources/images/devguide/getting-started/my-first-app.png' alt="Output of getting started app")
:markdown
### Make some changes
**`live-server`** detects changes to our files and refreshes the browser page for us automatically.
Try changing the message to "My SECOND Angular 2 app".
The TypeScript compiler in the first terminal window is watching our source code. It recompiles and produces
the revised *app.js*. The `live-server` sees that change and reloads the browser.
Keep `live-server` running in this terminal window. You can stop it anytime with `Ctrl-C`.
.l-main-section
:markdown
## What have we done?
Our first application doesn't do much. It's basically "Hello, World" for Angular 2.
We kept it simple in our first pass: we wrote a little Angular component,
we added some JavaScript libraries to `index.html`, and launched with a
static file server. That's about all we'd expect to do for a "Hello, World" app.
**We have greater ambitions.**
We won't ask Angular to build "Hello, World".
We are asking it to help us build sophisticated applications with sophisticated requirements.
So we made some strategic technology investments to reach our larger goals
* our application loads faster with libraries installed locally and
we can develop offline if we wish.
* we're pre-compiling our TypeScript.
* we're running the compiler and live-server with commands that give us immediate feedback as we make changes.
The good news is that the overhead of setup is (mostly) behind us.
We're about to build a small application that demonstrates the great things
we can build with Angular 2.
<!--TODO: Join us on the [Tour of Heroes](./toh-pt1) -->
<!-- Move this to the Style Guide when we have one -->
.l-main-section
:markdown
<a id="tsconfig"></a>
### Appendix: TypeScript configuration
We added a TypeScript configuration file (`tsconfig.js`) to our project to
guide the compiler as it generates JavaScript files.
Get details about `tsconfig.js` from the official
[TypeScript wiki](https://github.com/Microsoft/TypeScript/wiki/tsconfig.json).
We'd like a moment to discuss the `noImplicitAny` flag.
TypeScript developers disagree about whether it should be `true` or `false`.
There is no correct answer and we can change the flag later.
But our choice now can make a difference in larger projects so it merits
discussion.
When the `noImplicitAny` flag is `false`,
the compiler silently defaults the type of a variable to `any` if it cannot infer
the type based on how the variable is used. That's what we mean by "implicitly `any`".
When the `noImplicitAny` flag is `true` and the TypeScript compiler cannot infer
the type, it still generates the JavaScript files but
it also reports an error.
For this project and the other examples in this Developer Guide
we set the `noImplicitAny` flag to `false`.
Developers who prefer stricter type checking should set the `noImplicitAny` flag to `true`.
We can still set a variable's type to `any` if
that seems like the best choice. We'd be doing so explicitly after
giving the matter some thought.
If we set the `noImplicitAny` flag to `true`, we may get implicit index errors as well.
If we feel these are more annoying than helpful,
we can suppress them with the following additional flag.
```
"suppressImplicitAnyIndexErrors":true
```