docs(quickstart): quickstart revised with verbose mode toggle button
This commit is contained in:
parent
ad7f172ea5
commit
d59b05adde
@ -46,7 +46,64 @@ mixin makeJson( filePath, jsonConfig, title, stylePatterns)
|
|||||||
else
|
else
|
||||||
!= styleString(jsonExtract, stylePatterns)
|
!= styleString(jsonExtract, stylePatterns)
|
||||||
|
|
||||||
|
- // Open (and close) an explanation <div>. See QuickStart
|
||||||
|
script.
|
||||||
|
function why(id, backTo) {
|
||||||
|
var id = "#"+id;
|
||||||
|
var el = document.querySelector(id);
|
||||||
|
el.hidden=el.hidden=!el.hidden;
|
||||||
|
|
||||||
|
if (el.hidden && backTo){
|
||||||
|
// the next line is required to work around a bug in WebKit (Chrome / Safari)
|
||||||
|
location.href = "#";
|
||||||
|
location.href = "#" + backTo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
script.
|
||||||
|
function verbose(isVerbose) {
|
||||||
|
isVerbose = !! isVerbose;
|
||||||
|
var el = document.querySelector('button.verbose.off');
|
||||||
|
el.style.display = isVerbose ? 'block' : 'none';
|
||||||
|
var el = document.querySelector('button.verbose.on');
|
||||||
|
el.style.display = isVerbose ? 'none' : 'block';
|
||||||
|
|
||||||
|
CCSStylesheetRuleStyle('main','.l-verbose-section', 'display',
|
||||||
|
isVerbose ? 'block' : 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
script.
|
||||||
|
function CCSStylesheetRuleStyle(stylesheet, selectorText, style, value){
|
||||||
|
/* returns the value of the element style of the rule in the stylesheet
|
||||||
|
* If no value is given, reads the value
|
||||||
|
* If value is given, the value is changed and returned
|
||||||
|
* If '' (empty string) is given, erases the value.
|
||||||
|
* The browser will apply the default one
|
||||||
|
*
|
||||||
|
* string stylesheet: part of the .css name to be recognized, e.g. 'default'
|
||||||
|
* string selectorText: css selector, e.g. '#myId', '.myClass', 'thead td'
|
||||||
|
* string style: camelCase element style, e.g. 'fontSize'
|
||||||
|
* string value optional : the new value
|
||||||
|
*/
|
||||||
|
var CCSstyle = undefined, rules, sheet;
|
||||||
|
for(var m in document.styleSheets){
|
||||||
|
sheet = document.styleSheets[m];
|
||||||
|
if(sheet.href && sheet.href.indexOf(stylesheet) != -1){
|
||||||
|
rules = sheet[document.all ? 'rules' : 'cssRules'];
|
||||||
|
for(var n in rules){
|
||||||
|
console.log(rules[n].selectorText);
|
||||||
|
if(rules[n].selectorText == selectorText){
|
||||||
|
CCSstyle = rules[n].style;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(value == undefined)
|
||||||
|
return CCSstyle[style]
|
||||||
|
else
|
||||||
|
return CCSstyle[style] = value
|
||||||
|
}
|
||||||
//---------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------
|
||||||
- var translatePath = function(filePath, region) {
|
- var translatePath = function(filePath, region) {
|
||||||
- filePath = filePath.trim();
|
- filePath = filePath.trim();
|
||||||
@ -134,6 +191,7 @@ mixin makeJson( filePath, jsonConfig, title, stylePatterns)
|
|||||||
- return source;
|
- return source;
|
||||||
- }
|
- }
|
||||||
|
|
||||||
|
|
||||||
- var getFragFilePath = function (filePath, region) {
|
- var getFragFilePath = function (filePath, region) {
|
||||||
- filePath = filePath.trim();
|
- filePath = filePath.trim();
|
||||||
- var extn = getExtn(filePath);
|
- var extn = getExtn(filePath);
|
||||||
|
@ -36,7 +36,6 @@
|
|||||||
.then(null, console.error.bind(console));
|
.then(null, console.error.bind(console));
|
||||||
</script>
|
</script>
|
||||||
<!-- #enddocregion systemjs -->
|
<!-- #enddocregion systemjs -->
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<!-- 3. Display the application -->
|
<!-- 3. Display the application -->
|
||||||
@ -45,5 +44,4 @@
|
|||||||
<my-app>Loading...</my-app>
|
<my-app>Loading...</my-app>
|
||||||
</body>
|
</body>
|
||||||
<!-- #enddocregion my-app -->
|
<!-- #enddocregion my-app -->
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -81,7 +81,7 @@ nav a.router-link-active {
|
|||||||
left: .1em;
|
left: .1em;
|
||||||
}
|
}
|
||||||
.items li.selected:hover {
|
.items li.selected:hover {
|
||||||
background-color: #BBD8DC !important;
|
background-color: #BBD8DC;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
.items .text {
|
.items .text {
|
||||||
|
@ -78,6 +78,11 @@
|
|||||||
"intro": "Angular 1 applications can be incrementally upgraded to Angular 2."
|
"intro": "Angular 1 applications can be incrementally upgraded to Angular 2."
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"typescript-configuration": {
|
||||||
|
"title": "TypeScript Configuration",
|
||||||
|
"intro": "TypeScript configuration for Angular 2 developers"
|
||||||
|
},
|
||||||
|
|
||||||
"glossary": {
|
"glossary": {
|
||||||
"title": "Glossary",
|
"title": "Glossary",
|
||||||
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary"
|
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary"
|
||||||
|
151
public/docs/ts/latest/guide/typescript-configuration.jade
Normal file
151
public/docs/ts/latest/guide/typescript-configuration.jade
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
include ../../../../_includes/_util-fns
|
||||||
|
|
||||||
|
:marked
|
||||||
|
TypeScript is a primary language for Angular application development.
|
||||||
|
|
||||||
|
TypeScript is a dialect of JavaScript with design-time support for type-safety and tooling.
|
||||||
|
|
||||||
|
Browsers can't execute TypeScript directly. It has to be "transpiled" into JavaScript with the *tsc* compiler
|
||||||
|
and that effort requires some configuration.
|
||||||
|
|
||||||
|
This chapter covers some aspects of TypeScript configuration and the TypeScript environment
|
||||||
|
that are important to Angular developers.
|
||||||
|
|
||||||
|
a(id="tsconfig")
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## *tsconfig.json*
|
||||||
|
We typically add a TypeScript configuration file (`tsconfig.json`) to our project to
|
||||||
|
guide the compiler as it generates JavaScript files.
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
Get details about `tsconfig.json` from the official
|
||||||
|
[TypeScript wiki](https://github.com/Microsoft/TypeScript/wiki/tsconfig.json).
|
||||||
|
:marked
|
||||||
|
We created the following `tsconfig.json` for the [QuickStart](../quickstart.html):
|
||||||
|
+makeJson('quickstart/ts/tsconfig.1.json', null, 'tsconfig.json')(format=".")
|
||||||
|
:marked
|
||||||
|
The options and flags in this file are essential for Angular 2 applications.
|
||||||
|
|
||||||
|
<a id="noImplicitAny"></a>
|
||||||
|
### *noImplicitAny* and *suppressImplicitAnyIndexErrors*
|
||||||
|
|
||||||
|
TypeScript developers disagree about whether the `noImplicitAny` flag 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 default),
|
||||||
|
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 *implicit `any`*.
|
||||||
|
|
||||||
|
We initialized the `noImplicitAny` flag to `false` in the QuickStart
|
||||||
|
to make learning TypeScript development easier.
|
||||||
|
|
||||||
|
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**.
|
||||||
|
Many seasoned developers prefer this stricter setting because type checking catches more
|
||||||
|
unintentional errors at compile time.
|
||||||
|
|
||||||
|
We can set a variable's type to `any` even when the `noImplicitAny` flag is `true`.
|
||||||
|
We do so when that seems like the best choice for the situation,
|
||||||
|
deliberately and explicitly, after giving the matter some thought.
|
||||||
|
|
||||||
|
If we set the `noImplicitAny` flag to `true`, we may get *implicit index errors* as well.
|
||||||
|
Most developers feel that *this particular error* is more annoying than helpful.
|
||||||
|
We can suppress them with the following additional flag.
|
||||||
|
code-example(format=".").
|
||||||
|
"suppressImplicitAnyIndexErrors":true
|
||||||
|
|
||||||
|
|
||||||
|
a(id="typings")
|
||||||
|
.l-main-section
|
||||||
|
:marked
|
||||||
|
## TypeScript Typings
|
||||||
|
Many JavaScript libraries such as jQuery, the Jasmine testing library, and Angular itself,
|
||||||
|
extend the JavaScript environment with features and syntax
|
||||||
|
that the TypeScript compiler doesn't recognize natively.
|
||||||
|
When the compiler doesn't recognize something, it throws an error.
|
||||||
|
|
||||||
|
We use [TypeScript type definition files](http://www.typescriptlang.org/Handbook#writing-dts-files)
|
||||||
|
— *d.ts files* — to tell the compiler about the libraries we load.
|
||||||
|
|
||||||
|
TypeScript-aware editors leverage these same definition files to display type information about library features.
|
||||||
|
|
||||||
|
Many libraries include their definition files in their npm packages where both the TypeScript compiler and editors
|
||||||
|
can find them. Angular is one such library.
|
||||||
|
Peek into the `node_modules/angular2/` folder of any Angular application to see several `...d.ts` files that describe parts of Angular.
|
||||||
|
|
||||||
|
**We do nothing to get *typings* files for library packages with bundled *d.ts* files.**
|
||||||
|
|
||||||
|
### Manual typings
|
||||||
|
Sadly, many libraries — jQuery, Jasmine, and Lodash among them — do *not* include `d.ts` files in their npm packages.
|
||||||
|
Fortunately, either their authors or community contributors have created separate *d.ts* files for these libraries and
|
||||||
|
published them in well-known locations.
|
||||||
|
The *typings* tool can find and fetch these files for us.
|
||||||
|
|
||||||
|
We installed the [typings](https://github.com/typings/typings/blob/master/README.md) tool
|
||||||
|
with npm (it's listed among the *devDependencies* in the `package.json`) and added an npm script
|
||||||
|
to run that tool automatically after *npm* installation completes.
|
||||||
|
+makeJson('quickstart/ts/package.1.json', {paths: 'scripts.postinstall'}, 'package.json (postinstall)')(format=".")
|
||||||
|
:marked
|
||||||
|
This *typings* tool command installs the *d.ts* files that we identify in a `typings.json` file
|
||||||
|
such as this one from the [QuickStart](../quickstart.html):
|
||||||
|
+makeJson('quickstart/ts/typings.1.json', null, 'typings.json')(format=".")
|
||||||
|
:marked
|
||||||
|
We identified only one *typings* file in the QuickStart, the *d.ts* file for
|
||||||
|
[es6-shim](https://github.com/paulmillr/es6-shim/blob/master/README.md) that brings ES2015/ES6
|
||||||
|
capabilities to our ES5 browsers.
|
||||||
|
QuickStart itself doesn't need this shim but many of the documentation samples do
|
||||||
|
and most of us would be disappointed if typical ES2015 features didn't work out-of-the-box.
|
||||||
|
|
||||||
|
We can also run the *typings* tool ourselves. The following command lists the locally installed typings files.
|
||||||
|
code-example(format="").
|
||||||
|
npm run typings -- list
|
||||||
|
:marked
|
||||||
|
The following command installs the typings file for the Jasmine test library and updates the `typings.config`
|
||||||
|
so we that we get it automatically the next time.
|
||||||
|
code-example(format="").
|
||||||
|
npm run typings -- install jasmine --ambient --save
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
The [–– option](https://docs.npmjs.com/cli/run-script) is important;
|
||||||
|
it tells npm to pass all arguments to the right of `--` to the *typings* command.
|
||||||
|
|
||||||
|
Learn about the features of the *typings* tool at its [site on github](https://github.com/typings/typings/blob/master/README.md).
|
||||||
|
:marked
|
||||||
|
#### Typing file collisions
|
||||||
|
|
||||||
|
The TypeScript compiler does not tolerate redefinition of a type. For example, it throws an error if it's given two definitions for
|
||||||
|
the `Promise` type.
|
||||||
|
|
||||||
|
Double definitions are common. In fact, the `typings` tool deliberately creates
|
||||||
|
duplicate sets of typings (for reasons best explained elsewhere).
|
||||||
|
Look in the project structure for the *typings folder* where we should find something like:
|
||||||
|
.filetree
|
||||||
|
.file typings
|
||||||
|
.children
|
||||||
|
.file browser
|
||||||
|
.children
|
||||||
|
.file ambient
|
||||||
|
.children
|
||||||
|
.file es6-shim
|
||||||
|
.children
|
||||||
|
.file es6-shim.d.ts
|
||||||
|
.children
|
||||||
|
.file main
|
||||||
|
.children
|
||||||
|
.file ambient
|
||||||
|
.children
|
||||||
|
.file es6-shim
|
||||||
|
.children
|
||||||
|
.file es6-shim.d.ts
|
||||||
|
.children
|
||||||
|
.file browser.d.ts
|
||||||
|
.file main.d.ts
|
||||||
|
:marked
|
||||||
|
The `es6-shim` typings are duplicated and the `browser.d.ts` and `main.d.ts` have overlapping content.
|
||||||
|
|
||||||
|
We must tell the compiler to ignore one or the other.
|
||||||
|
We removed the `main` set from consideration in the `exclude` section of our `tsconfig.json` file:
|
||||||
|
+makeJson('quickstart/ts/tsconfig.1.json', {paths: 'exclude'}, 'tsconfig.json (exclude)')(format=".")
|
||||||
|
:marked
|
@ -1,270 +1,431 @@
|
|||||||
include ../../../_includes/_util-fns
|
include ../../../_includes/_util-fns
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
Let's start from zero and build a super simple Angular 2 application in TypeScript.
|
Our QuickStart goal is to build and run a super-simple Angular 2 application in TypeScript.
|
||||||
|
|
||||||
.callout.is-helpful
|
|
||||||
header Don't want TypeScript?
|
|
||||||
:marked
|
|
||||||
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
|
|
||||||
:marked
|
|
||||||
## See It Run!
|
## See It Run!
|
||||||
|
|
||||||
Running the [live example](/resources/live-examples/quickstart/ts/plnkr.html)
|
Try this <a href="/resources/live-examples/quickstart/ts/plnkr.html" target="_blank">live example</a>
|
||||||
is the quickest way to see an Angular 2 app come to life.
|
which loads the sample app in <a href="http://plnkr.co/" title="Plunker" target="_blank">plunker</a>
|
||||||
|
|
||||||
Clicking that link fires up a browser, loads the sample in [plunker](http://plnkr.co/ "Plunker"),
|
|
||||||
and displays a simple message:
|
and displays a simple message:
|
||||||
|
|
||||||
figure.image-display
|
figure.image-display
|
||||||
img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="Output of quickstart app")
|
img(src='/resources/images/devguide/quickstart/my-first-app.png' alt="Output of QuickStart app")
|
||||||
:marked
|
:marked
|
||||||
Here is the file structure:
|
Of course we don't build apps to run in plunker.
|
||||||
.filetree
|
The following steps establish a development environment for the documentation samples
|
||||||
.file angular2-quickstart
|
that also can be the foundation for our real world applications. At a high level, we will
|
||||||
.children
|
|
||||||
.file app
|
|
||||||
.children
|
|
||||||
.file app.component.ts
|
|
||||||
.file main.ts
|
|
||||||
.file index.html
|
|
||||||
.file license.md
|
|
||||||
:marked
|
|
||||||
Functionally, it's an `index.html` and two TypeScript files in an `app/` folder.
|
|
||||||
We can handle that!
|
|
||||||
|
|
||||||
Of course we won't build many apps that only run in plunker.
|
- set up the [development environment](#devenv)
|
||||||
Let's follow a process that's closer to what we'd do in real life.
|
- write the app's Angular [root component](#component)
|
||||||
|
- write [main.ts](#main) which tells Angular to display the root component
|
||||||
1. Set up our development environment
|
- write the [host web page](#index) (`index.html`)
|
||||||
1. Write the Angular root component for our app
|
|
||||||
1. Bootstrap it to take control of the main web page
|
|
||||||
1. Write the main page (`index.html`)
|
|
||||||
|
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
We really can build the QuickStart from scratch in five minutes
|
We'll see many code blocks as we pursue this agenda. They're all easy to copy and paste:
|
||||||
if we follow the instructions and ignore the commentary.
|
code-example(format='.', language='html').
|
||||||
|
Click the glyph on the right to copy code snippets to the clipboard ⇨⇨⇨⇨⇨⇨⇨⇨⇨⇨
|
||||||
|
|
||||||
Most of us will be interested in the "why" as well as the "how" and that will take longer.
|
button(class="verbose off md-primary md-button md-ink-ripple", type="button", onclick="verbose(false)").
|
||||||
:marked
|
Hide explanations
|
||||||
|
button(class="verbose on md-primary md-button md-ink-ripple", type="button", onclick="verbose(true)").
|
||||||
|
View explanations
|
||||||
|
.l-verbose-section
|
||||||
|
:marked
|
||||||
|
*Explanations* describe the concepts and reasons behind the instructions.
|
||||||
|
Explanations have a thin border on the left like *this* block of text.
|
||||||
|
|
||||||
|
Click *Hide Explanations* to show only the instructions.
|
||||||
|
Click it again to see everything again.
|
||||||
|
|
||||||
|
a(id="devenv")
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Development Environment
|
## Development Environment
|
||||||
|
|
||||||
We'll need a place to stand (the application project folder),
|
We need to set up our development environment with
|
||||||
some TypeScript configuration, and some libraries for development and runtime.
|
* an [application project folder](#app-folder)
|
||||||
|
* a [tsconfig.json](#tsconfig) to guide the TypeScript compiler
|
||||||
### Create a new project folder
|
* a [typings.json](#typings) to install TypeScript definition files
|
||||||
|
* a [package.json](#package-json) to install *npm* packages with scripts and other assets our app will need.
|
||||||
|
|
||||||
|
a(id="app-folder")
|
||||||
|
:marked
|
||||||
|
Create a **new project folder**
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
mkdir angular2-quickstart
|
mkdir angular2-quickstart
|
||||||
cd angular2-quickstart
|
cd angular2-quickstart
|
||||||
|
|
||||||
|
a(id="tsconfig")
|
||||||
:marked
|
:marked
|
||||||
### Configure TypeScript
|
|
||||||
|
|
||||||
We must guide the TypeScript compiler with very specific settings.
|
|
||||||
|
|
||||||
Add a **tsconfig.json** file to the project folder and copy/paste the following:
|
Add a **tsconfig.json** file to the project folder and copy/paste the following:
|
||||||
+makeJson('quickstart/ts/tsconfig.1.json', null, 'tsconfig.json')(format=".")
|
+makeJson('quickstart/ts/tsconfig.1.json', null, 'tsconfig.json')(format=".")
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
We explore the `tsconfig.json` in an [appendix below](#tsconfig)
|
|
||||||
:marked
|
:marked
|
||||||
### TypeScript Typings
|
This `tsconfig.json` file guides the TypeScript compiler.
|
||||||
|
Learn more about it in the
|
||||||
Many JavaScript libraries extend the JavaScript environment with features and syntax
|
<a href="guide/typescript-configuration.html#tsconfig" target="_blank">TypeScript Configuration</a> chapter.
|
||||||
that the TypeScript compiler doesn't recognize natively. We teach it about these capabilities with
|
|
||||||
[TypeScript type definition files](http://www.typescriptlang.org/Handbook#writing-dts-files)
|
|
||||||
— *d.ts files* — which we identify in a `typings.json` file.
|
|
||||||
|
|
||||||
|
a(id="typings")
|
||||||
|
:marked
|
||||||
Add a **typings.json** file to the project folder and copy/paste the following:
|
Add a **typings.json** file to the project folder and copy/paste the following:
|
||||||
+makeJson('quickstart/ts/typings.1.json', null, 'typings.json')(format=".")
|
+makeJson('quickstart/ts/typings.1.json', null, 'typings.json')(format=".")
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
We go a little deeper into *typings* in an [appendix below](#typings)
|
|
||||||
:marked
|
|
||||||
### Add the libraries we need
|
|
||||||
|
|
||||||
We recommend the **npm** package manager for acquiring and managing our development libraries.
|
.l-verbose-section
|
||||||
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
:marked
|
||||||
Don't have npm?
|
Many JavaScript libraries extend the JavaScript environment with features and syntax
|
||||||
[Get it now](https://docs.npmjs.com/getting-started/installing-node "Installing Node.js and updating npm")
|
that the TypeScript compiler doesn't recognize natively. We teach it about these capabilities with
|
||||||
because we're going to use it now and repeatedly throughout this documentation.
|
<a href="http://www.typescriptlang.org/Handbook#writing-dts-files" target="_blank">TypeScript type definition files</a>
|
||||||
|
— *d.ts files* — which we identify in a `typings.json` file.
|
||||||
|
|
||||||
|
We go a little deeper into *typings* in the
|
||||||
|
<a href="guide/typescript-configuration.html#typings" target="_blank">TypeScript Configuration</a> chapter.
|
||||||
|
|
||||||
|
a(id="package-json")
|
||||||
:marked
|
:marked
|
||||||
Add a **package.json** file to the project folder and copy/paste the following:
|
Add a **package.json** file to the project folder and copy/paste the following:
|
||||||
+makeJson('quickstart/ts/package.1.json', null, 'package.json')(format=".")
|
+makeJson('quickstart/ts/package.1.json', null, 'package.json')(format=".")
|
||||||
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
Itching to know the details? We explain in the [appendix below](#package-json)
|
|
||||||
:marked
|
:marked
|
||||||
Install these packages. Open a terminal window (command window in Windows) and
|
**Install these packages** by entering the following *npm* command in a terminal window (command window in Windows):
|
||||||
run this npm command.
|
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
npm install
|
npm install
|
||||||
:marked
|
|
||||||
.l-sub-section
|
.alert.is-important
|
||||||
:marked
|
:marked
|
||||||
Scary <span style="color:red; font-weight: bold">error messages in red</span> may appear **during** install.
|
Scary <span style="color:red; font-weight: bold">error messages in red</span> may appear **during** install.
|
||||||
Ignore them. The install will succeed. See the [appendix below](#npm-errors) for more information.
|
The install typically recovers from these errors and finishes successfully.
|
||||||
|
.l-verbose-section(class="l-verbose-inherit")
|
||||||
|
:marked
|
||||||
|
#### npm errors and warnings
|
||||||
|
|
||||||
|
All is well if there are no console messages starting with `npm ERR!` *at the end* of **npm install**.
|
||||||
|
There might be a few `npm WARN` messages along the way — and that is perfectly fine.
|
||||||
|
|
||||||
|
We often see an `npm WARN` message after a series of `gyp ERR!` messages.
|
||||||
|
Ignore them. A package may try to re-compile itself using `node-gyp`.
|
||||||
|
If the re-compile fails, the package recovers (typically with a pre-built version)
|
||||||
|
and everything works.
|
||||||
|
|
||||||
|
Just make sure there are no `npm ERR!` messages at the end of `npm install`.
|
||||||
|
.l-verbose-section
|
||||||
|
:marked
|
||||||
|
### Adding the libraries we need with *npm*
|
||||||
|
Angular application developers rely on the <a href="https://docs.npmjs.com/" target="_blank"><i>npm</i></a>
|
||||||
|
package manager to acquire the libraries their apps require.
|
||||||
|
|
||||||
|
Don't have npm?
|
||||||
|
<a href="https://docs.npmjs.com/getting-started/installing-node" target="_blank" title="Installing Node.js and updating npm">Get it now</a>
|
||||||
|
because we're going to use it now and repeatedly throughout this documentation.
|
||||||
|
|
||||||
|
The Angular team recommends the starter-set of packages specified in the `dependencies` and `devDependencies`
|
||||||
|
sections of this QuickStart
|
||||||
|
<a href="https://docs.npmjs.com/files/package.json" target="_blank">package.json</a> file.
|
||||||
|
|
||||||
|
+makeJson('quickstart/ts/package.1.json',{ paths: 'dependencies, devDependencies'}, 'package.json (dependencies)')(format=".")
|
||||||
|
:marked
|
||||||
|
There are other possible package choices.
|
||||||
|
We're recommending this particular set that we know work well together.
|
||||||
|
Feel free to make substitutions later to suit your tastes and experience.
|
||||||
|
|
||||||
|
A `package.json` has an optional **scripts** section where we can define helpful
|
||||||
|
commands for development and build tasks.
|
||||||
|
We've included a number of such scripts in our suggested `package.json`:
|
||||||
|
+makeJson('quickstart/ts/package.1.json',{ paths: 'scripts'}, 'package.json (scripts)')(format=".")
|
||||||
|
|
||||||
|
:marked
|
||||||
|
We execute most npm scripts in the following way: `npm run` + *script-name*.
|
||||||
|
Some commands (such as `start` don't require the `run` keyword).
|
||||||
|
|
||||||
|
Here's what these scripts do:
|
||||||
|
|
||||||
|
* `npm start` - run the compiler and a server at the same time, both in "watch mode"
|
||||||
|
|
||||||
|
* `npm run tsc` - run the TypeScript compiler once
|
||||||
|
|
||||||
|
* `npm run tsc:w` - run the TypeScript compiler in watch mode;
|
||||||
|
the process keeps running, awaiting changes to TypeScript files and re-compiling when it sees them.
|
||||||
|
|
||||||
|
* `npm run lite` - run the <a href="https://www.npmjs.com/package/lite-server" target="_blank">lite-server</a>,
|
||||||
|
a light-weight, static file server, written and maintained by
|
||||||
|
<a href="http://johnpapa.net/" target="_blank">John Papa</a>
|
||||||
|
with excellent support for Angular apps that use routing.
|
||||||
|
|
||||||
|
* `npm run typings` - runs the [*typings* tool](#typings)
|
||||||
|
|
||||||
|
* `npm postinstall` - called by *npm* automatically *after* it successfully completes package installation.
|
||||||
|
This script installs the [TypeScript definition files](#typings) this app requires.
|
||||||
|
|
||||||
:marked
|
:marked
|
||||||
**We're all set.** Let's write some code.
|
**We're all set.** Let's write some code.
|
||||||
|
|
||||||
|
|
||||||
|
a(id="component")
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Our First Angular Component
|
## Our First Angular Component
|
||||||
|
Let's create a folder to hold our application and add a super-simple Angular component.
|
||||||
|
|
||||||
The *Component* is the most fundamental of Angular concepts.
|
**Create an *app* sub-folder** off the root directory and make it the current directory
|
||||||
A component manages a view - a piece of the web page where we display information
|
|
||||||
to the user and respond to user feedback.
|
|
||||||
|
|
||||||
Technically, a component is a class that controls a view template.
|
|
||||||
We'll write a lot of them as we build Angular apps. This is our first attempt
|
|
||||||
so we'll keep it ridiculously simple.
|
|
||||||
|
|
||||||
### Create an application source sub-folder
|
|
||||||
|
|
||||||
We like to keep our application code in a sub-folder off the root called `app/`.
|
|
||||||
Execute the following command in the console window.
|
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
mkdir app
|
mkdir app
|
||||||
cd app
|
cd app
|
||||||
|
|
||||||
|
a(id="app-component")
|
||||||
:marked
|
:marked
|
||||||
### Add the component file
|
**Add a component file** named *app.component.ts* and paste the following lines:
|
||||||
Now add a file named **app.component.ts** and paste the following lines:
|
|
||||||
+makeExample('quickstart/ts/app/app.component.ts', null, 'app/app.component.ts')(format=".")
|
+makeExample('quickstart/ts/app/app.component.ts', null, 'app/app.component.ts')(format=".")
|
||||||
:marked
|
|
||||||
Let's review this file in detail, starting at the bottom where we define a class.
|
|
||||||
|
|
||||||
### The Component class
|
.l-verbose-section
|
||||||
At the bottom of the file is an empty, do-nothing class named `AppComponent`.
|
|
||||||
When we're ready to build a substantive application,
|
|
||||||
we can expand this class with properties and application logic.
|
|
||||||
Our `AppComponent` class is empty because we don't need it to do anything in this QuickStart.
|
|
||||||
|
|
||||||
### Modules
|
|
||||||
Angular apps are modular. They consist of many files each dedicated to a purpose.
|
|
||||||
|
|
||||||
Most application files *export* one thing such as a component.
|
|
||||||
Our `app.component` file exports the `AppComponent`.
|
|
||||||
+makeExample('quickstart/ts/app/app.component.ts', 'export', 'app/app.component.ts (export)')(format=".")
|
|
||||||
:marked
|
|
||||||
The act of exporting turns the file into a module.
|
|
||||||
The name of the file (without extension) is usually the name of the module.
|
|
||||||
Accordingly, '*app.component*' is the name of our first module.
|
|
||||||
|
|
||||||
A more sophisticated application would have child components that descended from
|
|
||||||
`AppComponent` in a visual tree.
|
|
||||||
A more sophisticated app would have more files and modules, at least as many as it had components.
|
|
||||||
|
|
||||||
This Quickstart isn't sophisticated; one component is all we need.
|
|
||||||
Yet modules play a fundamental organizational role in even this small app.
|
|
||||||
|
|
||||||
Modules rely on other modules. In TypeScript Angular apps, when we need something
|
|
||||||
provided by another module, we import it.
|
|
||||||
When another module needs to refer to `AppComponent`, it imports the `AppComponent` *symbol* like this:
|
|
||||||
+makeExample('quickstart/ts/app/main.ts', 'app-component','app/main.ts (import)')(format=".")
|
|
||||||
:marked
|
|
||||||
Angular is also modular. It is a collection of library modules.
|
|
||||||
Each library is itself a module made up of several, related feature modules.
|
|
||||||
|
|
||||||
When we need something from Angular, we import it from an Angular library module.
|
|
||||||
We need something from Angular right now to help us define metadata about our component.
|
|
||||||
|
|
||||||
### Component Metadata
|
|
||||||
A class becomes an Angular component when we give it metadata.
|
|
||||||
Angular needs the metadata to understand how to construct the view
|
|
||||||
and how the component interacts with other parts of the application.
|
|
||||||
|
|
||||||
We define a component's metadata with the Angular `Component` function.
|
|
||||||
We access that function by importing it from the primary Angular library,`angular2/core`.
|
|
||||||
+makeExample('quickstart/ts/app/app.component.ts', 'import', 'app/app.component.ts (import)')(format=".")
|
|
||||||
:marked
|
|
||||||
In TypeScript we apply that function to the class as a *decorator*
|
|
||||||
by prefixing it with the **@** symbol and invoking it
|
|
||||||
just above the component class:
|
|
||||||
+makeExample('quickstart/ts/app/app.component.ts', 'metadata', 'app/app.component.ts (metadata)')
|
|
||||||
:marked
|
|
||||||
`@Component` tells Angular that this class *is an Angular component*.
|
|
||||||
The configuration object passed to the `@Component` method has two
|
|
||||||
fields, a `selector` and a `template`.
|
|
||||||
|
|
||||||
The `selector` specifies a simple 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 in the host HTML.
|
|
||||||
|
|
||||||
.alert.is-helpful
|
|
||||||
:marked
|
:marked
|
||||||
Remember the `my-app` selector! We'll need that information when we write our `index.html`
|
### AppComponent is the root of the application
|
||||||
|
|
||||||
|
Every Angular app has at least one root component, conventionally named `AppComponent`,
|
||||||
|
that hosts the client user experience.
|
||||||
|
|
||||||
|
Components are the basic building blocks of Angular applications.
|
||||||
|
A component controls a portion of the screen — a *view* — through its associated template.
|
||||||
|
|
||||||
|
This QuickStart has only one, extremely simple component.
|
||||||
|
But it has the essential structure of every component we'll ever write:
|
||||||
|
|
||||||
|
* One or more <a href="javascript: why('component-import')">import</a>
|
||||||
|
statements to reference the things we need.
|
||||||
|
|
||||||
|
* A <a href="javascript: why('decorator')">@Component decorator</a>
|
||||||
|
that tells Angular what template to use and how to create the component.
|
||||||
|
|
||||||
|
* A <a href="javascript: why('class')">component class</a>
|
||||||
|
that controls the appearance and behavior of a view through its template.
|
||||||
|
|
||||||
|
a(id="component-import")
|
||||||
|
:marked
|
||||||
|
### Import
|
||||||
|
|
||||||
|
Angular apps are modular. They consist of many files each dedicated to a purpose.
|
||||||
|
|
||||||
|
Angular itself is modular. It is a collection of library modules
|
||||||
|
each made up of several, related features that we'll use to build our application.
|
||||||
|
|
||||||
|
When we need something from a module, we import it.
|
||||||
|
Here we import the Angular `Component` decorator function from the
|
||||||
|
main Angular library module because we need it to define our component.
|
||||||
|
+makeExample('quickstart/ts/app/app.component.ts', 'import', 'app/app.component.ts (import)')(format=".")
|
||||||
|
|
||||||
|
a(id="component-decorator")
|
||||||
|
:marked
|
||||||
|
### @Component decorator
|
||||||
|
|
||||||
|
`Component` is a **decorator** function that takes a *metadata* object.
|
||||||
|
The metadata tell Angular how to create and use this component.
|
||||||
|
|
||||||
|
We apply this function to the component class
|
||||||
|
by prefixing the function with the **@** symbol and invoking it with the metadata object.
|
||||||
|
just above the class:
|
||||||
|
+makeExample('quickstart/ts/app/app.component.ts', 'metadata', 'app/app.component.ts (metadata)')(format=".")
|
||||||
|
:marked
|
||||||
|
This particular metadata object has two fields, a `selector` and a `template`.
|
||||||
|
|
||||||
|
The **selector** specifies a simple CSS selector for an HTML element that represents the component.
|
||||||
|
|
||||||
|
>The element for this component is named `my-app`.
|
||||||
|
Angular creates and displays an instance of our `AppComponent`
|
||||||
|
wherever it encounters a `my-app` element in the host HTML.
|
||||||
|
|
||||||
|
The **template** specifies the component's companion template,
|
||||||
|
written in an enhanced form of HTML that tells Angular how to render this component's view.
|
||||||
|
|
||||||
|
>Our template is a single line of HTML announcing "*My First Angular App*".
|
||||||
|
|
||||||
|
>A more advanced template could contain data bindings to component properties
|
||||||
|
and might identify other application components which have their own templates.
|
||||||
|
These templates might identify yet other components.
|
||||||
|
In this way an Angular application becomes a tree of components.
|
||||||
|
|
||||||
|
a(id="component-class")
|
||||||
|
:marked
|
||||||
|
### Component class
|
||||||
|
At the bottom of the file is an empty, do-nothing class named `AppComponent`.
|
||||||
|
+makeExample('quickstart/ts/app/app.component.ts', 'export', 'app/app.component.ts (class)')(format=".")
|
||||||
|
:marked
|
||||||
|
When we're ready to build a substantive application,
|
||||||
|
we can expand this class with properties and application logic.
|
||||||
|
Our `AppComponent` class is empty because we don't need it to do anything in this QuickStart.
|
||||||
|
|
||||||
|
We **export** `AppComponent` so that we can **import** it elsewhere in our application,
|
||||||
|
as we'll see when we create `main.ts`.
|
||||||
|
|
||||||
|
a(id="main")
|
||||||
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
The `template` property holds the component's companion template.
|
## Show it with *main.ts*
|
||||||
A template is a form of HTML that tells Angular how to render a view.
|
Now we need something to tell Angular to load the root component
|
||||||
Our template is a single line of HTML announcing "My First Angular App".
|
|
||||||
|
|
||||||
Now we need something to tell Angular to load this component.
|
|
||||||
|
|
||||||
### Bootstrap it
|
|
||||||
|
|
||||||
Add a new file , `main.ts`, to the `app/` folder as follows:
|
Add a new file , `main.ts`, to the `app/` folder as follows:
|
||||||
+makeExample('quickstart/ts/app/main.ts', null, 'app/main.ts')(format=".")
|
+makeExample('quickstart/ts/app/main.ts', null, 'app/main.ts')(format=".")
|
||||||
:marked
|
|
||||||
We need two things to launch the application:
|
|
||||||
|
|
||||||
1. Angular's browser `bootstrap` function
|
.l-verbose-section
|
||||||
1. The application root component that we just wrote.
|
|
||||||
|
|
||||||
We import both. Then we call `bootstrap`, passing in the **root component type**,
|
|
||||||
`AppComponent`.
|
|
||||||
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
:marked
|
||||||
Learn why we import `bootstrap` from `angular2/platform/browser`
|
We import the two things we need to launch the application:
|
||||||
and why we create a separate *main.ts* file in the [appendix below](#main).
|
|
||||||
:marked
|
|
||||||
We've asked Angular to launch the app in a browser with our component at the root.
|
|
||||||
Where will Angular put it?
|
|
||||||
|
|
||||||
|
1. Angular's browser `bootstrap` function
|
||||||
|
1. The application root component, `AppComponent`.
|
||||||
|
|
||||||
|
Then we call `bootstrap` with `AppComponent`.
|
||||||
|
|
||||||
|
### Bootstrapping is platform-specific
|
||||||
|
Notice that we import the `bootstrap` function from `angular2/platform/browser`,
|
||||||
|
not `angular2/core`.
|
||||||
|
|
||||||
|
Bootstrapping isn't core because there isn't a single way to bootstrap the app.
|
||||||
|
True, most applications that run in a browser call the bootstrap function from
|
||||||
|
this library.
|
||||||
|
|
||||||
|
But it is possible to load a component in a different environment.
|
||||||
|
We might load it on a mobile device with [Apache Cordova](https://cordova.apache.org/) or [NativeScript](https://www.nativescript.org/).
|
||||||
|
We might wish to render the first page of our application on the server
|
||||||
|
to improve launch performance or facilitate
|
||||||
|
[SEO](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf).
|
||||||
|
|
||||||
|
These targets require a different kind of bootstrap function that we'd import from a different library.
|
||||||
|
|
||||||
|
### Why create a separate ***main.ts*** file?
|
||||||
|
|
||||||
|
The *main.ts* file is tiny. This is just a QuickStart.
|
||||||
|
We could have folded its few lines into the `app.component` file
|
||||||
|
and spared ourselves some complexity.
|
||||||
|
|
||||||
|
We'd rather demonstrate the proper way to structure an Angular application.
|
||||||
|
App bootstrapping is a separate concern from presenting a view.
|
||||||
|
Mixing concerns creates difficulties down the road.
|
||||||
|
We might launch the `AppComponent` in multiple environments with different bootstrappers.
|
||||||
|
Testing the component is much easier if it doesn't also try to run the entire application.
|
||||||
|
Let's make the small extra effort to do it *the right way*.
|
||||||
|
|
||||||
|
a(id="index")
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
## Add the `index.html`
|
## Add the `index.html`
|
||||||
|
The `index.html` is the web page that hosts the application
|
||||||
|
|
||||||
Angular displays our application in a specific location on our `index.html`.
|
Navigate to the **project root folder**.
|
||||||
It's time to create that file.
|
|
||||||
|
|
||||||
We won't put our `index.html` in the `app/` folder.
|
|
||||||
We'll locate it **up one level, in the project root folder**.
|
|
||||||
|
|
||||||
code-example(format="").
|
code-example(format="").
|
||||||
cd ..
|
cd ..
|
||||||
:marked
|
:marked
|
||||||
Now create the`index.html` file and paste the following lines:
|
Create an`index.html` file in this root folder and paste the following lines:
|
||||||
+makeExample('quickstart/ts/index.html', null, 'index.html')(format=".")
|
+makeExample('quickstart/ts/index.html', null, 'index.html')(format=".")
|
||||||
:marked
|
.l-verbose-section
|
||||||
There are three noteworthy sections of HTML:
|
:marked
|
||||||
|
There are three noteworthy sections of HTML
|
||||||
|
|
||||||
1. We load the JavaScript libraries we need; learn about them [below](#libraries).
|
1. The JavaScript [libraries](#libraries)
|
||||||
|
|
||||||
2. We configure something called `System` and ask it to import the
|
2. Configuration of [SystemJS](#systemjs) where we also import and run the
|
||||||
`main` file we just wrote.
|
`main` file that we just wrote.
|
||||||
|
|
||||||
3. We add the `<my-app>` tag in the `<body>`. **This is where our app lives!**
|
3. The [<my-app>](#my-app) tag in the `<body>` which is *where our app lives!*
|
||||||
|
|
||||||
Something has to find and load our application modules. We're using **SystemJS** to do that.
|
a(id="libraries")
|
||||||
There are other choices and we're not saying SystemJS is the best. We like it and it works.
|
:marked
|
||||||
|
### Libraries
|
||||||
|
We loaded the following scripts
|
||||||
|
+makeExample('quickstart/ts/index.html', 'libraries', 'index.html')(format=".")
|
||||||
|
:marked
|
||||||
|
We began with Internet Explorer polyfills.
|
||||||
|
IE requires polyfills to run
|
||||||
|
an application that relies on ES2015 promises and dynamic module loading.
|
||||||
|
Most applications need those capabilities and most applications
|
||||||
|
should run in Internet Explorer.
|
||||||
|
|
||||||
The specifics of SystemJS configuration are out of bounds.
|
Next are the polyfills for Angular2, `angular2-polyfills.js`.
|
||||||
We'll briefly describe this particular configuration in the [appendix below](#systemjs).
|
|
||||||
|
|
||||||
When Angular calls the `bootstrap` function in `main.ts`, it reads the `AppComponent`
|
Then the [SystemJS](#systemjs) library for module loading,
|
||||||
metadata, finds the `my-app` selector, locates an element tag named `my-app`,
|
followed by the Reactive Extensions RxJS library.
|
||||||
and loads our application between those tags.
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
Our QuickStart doesn't use the Reactive Extensions
|
||||||
|
but any substantial application will want them
|
||||||
|
when working with observables.
|
||||||
|
We added the library here in QuickStart so we don't forget later.
|
||||||
|
:marked
|
||||||
|
Finally, we loaded the web development version of Angular 2 itself.
|
||||||
|
|
||||||
|
We'll make different choices as we gain experience and
|
||||||
|
become more concerned about production qualities such as
|
||||||
|
load times and memory footprint.
|
||||||
|
|
||||||
|
a(id="systemjs")
|
||||||
|
:marked
|
||||||
|
### SystemJS Configuration
|
||||||
|
|
||||||
|
The QuickStart uses <a href="https://github.com/systemjs/systemjs" target="_blank">SystemJS</a>
|
||||||
|
to load application and library modules.
|
||||||
|
There are alternatives that work just fine including the well-regarded
|
||||||
|
<a href="https://webpack.github.io/" target="_blank">webpack</a>.
|
||||||
|
SystemJS happens to be a good choice but we want to be clear that it was a choice and not a preference.
|
||||||
|
|
||||||
|
All module loaders require configuration and all loader configuration
|
||||||
|
becomes complicated rather quickly as soon as the file structure diversifies and
|
||||||
|
we start thinking about building for production and performance.
|
||||||
|
|
||||||
|
We suggest becoming well-versed in the loader of your choice.
|
||||||
|
Learn more about SystemJS configuration
|
||||||
|
<a href="https://github.com/systemjs/systemjs/blob/master/docs/config-api.md" target="_blank">here</a>.
|
||||||
|
|
||||||
|
With those cautions in mind, what are we doing in this QuickStart configuration?
|
||||||
|
+makeExample('quickstart/ts/index.html', 'systemjs', 'index.html (System configuration)')(format=".")
|
||||||
|
:marked
|
||||||
|
The `packages` node tells SystemJS what to do when it sees a request for a
|
||||||
|
module from the `app/` folder.
|
||||||
|
|
||||||
|
Our QuickStart makes such requests when one of its
|
||||||
|
application TypeScript files has an import statement like this:
|
||||||
|
+makeExample('quickstart/ts/app/main.ts', 'app-component', 'main.ts (excerpt)')(format=".")
|
||||||
|
:marked
|
||||||
|
Notice that the module name (after `from`) does not mention a filename extension.
|
||||||
|
The `packages:` configuration tells SystemJS to default the extension to 'js', a JavaScript file.
|
||||||
|
|
||||||
|
That makes sense because we transpile TypeScript to JavaScript
|
||||||
|
<i>before</i> running the application</a>.
|
||||||
|
|
||||||
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
#### Transpiling in the browser
|
||||||
|
In the live example on plunker we transpile (AKA compile) to JavaScript in the browser
|
||||||
|
on the fly. That's fine for a demo. That's not our preference for development or production.
|
||||||
|
|
||||||
|
We recommend transpiling (AKA compiling) to JavaScript during a build phase
|
||||||
|
before running the application for several reasons including:
|
||||||
|
|
||||||
|
* We see compiler warnings and errors that are hidden from us in the browser.
|
||||||
|
|
||||||
|
* Pre-compilation simpifies the module loading process and
|
||||||
|
it's much easier to diagnose problem when this is a separate, external step.
|
||||||
|
|
||||||
|
* Pre-compilation means a faster user experience because the browser doesn't waste time compiling.
|
||||||
|
|
||||||
|
* We iterate development faster because we only re-compile changed files.
|
||||||
|
We notice the difference as soon as the app grows beyond a handful of files.
|
||||||
|
|
||||||
|
* Pre-compilation fits into a continuous integration process of build, test, deploy.
|
||||||
|
|
||||||
|
:marked
|
||||||
|
The `System.import` call tells SystemJS to import the `main` file
|
||||||
|
(`main.js` ... after transpiling `main.ts`, remember?).
|
||||||
|
`main` is where we tell Angular to launch the application.
|
||||||
|
We also catch and log launch errors to the console.
|
||||||
|
|
||||||
|
All other modules are loaded upon request
|
||||||
|
either by an import statement or by Angular itself.
|
||||||
|
|
||||||
|
a(id="my-app")
|
||||||
|
:marked
|
||||||
|
### *<my-app>*
|
||||||
|
When Angular calls the `bootstrap` function in `main.ts`, it reads the `AppComponent`
|
||||||
|
metadata, finds the `my-app` selector, locates an element tag named `my-app`,
|
||||||
|
and loads our application between those tags.
|
||||||
|
|
||||||
.l-main-section
|
.l-main-section
|
||||||
:marked
|
:marked
|
||||||
@ -348,377 +509,3 @@ figure.image-display
|
|||||||
demonstrates the great things we can build with Angular 2.
|
demonstrates the great things we can build with Angular 2.
|
||||||
|
|
||||||
Join us on the [Tour of Heroes Tutorial](./tutorial)!
|
Join us on the [Tour of Heroes Tutorial](./tutorial)!
|
||||||
|
|
||||||
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Appendices
|
|
||||||
The balance of this chapter is a set of appendices that
|
|
||||||
elaborate on some of the points we covered quickly above.
|
|
||||||
|
|
||||||
There is no essential material here. Continued reading is for the curious.
|
|
||||||
|
|
||||||
<a id="ie-polyfills"></a>
|
|
||||||
<a id="es6support"></a>
|
|
||||||
<a id="libraries"></a>
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Appendix: Libraries
|
|
||||||
We loaded the following scripts
|
|
||||||
+makeExample('quickstart/ts/index.html', 'libraries', 'index.html')(format=".")
|
|
||||||
:marked
|
|
||||||
We began with Internet Explorer polyfills.
|
|
||||||
IE requires polyfills to run
|
|
||||||
an application that relies on ES2015 promises and dynamic module loading.
|
|
||||||
Most applications need those capabilities and most applications
|
|
||||||
should run in Internet Explorer.
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
We can substitute the following libraries from a CDN:
|
|
||||||
+makeExample('router/ts/index.1.html','ie-cdn-polyfills')(format=".")
|
|
||||||
:marked
|
|
||||||
Next are the polyfills for Angular2, `angular2-polyfills.js`.
|
|
||||||
Then the [SystemJS library](#systemjs) for module loading,
|
|
||||||
followed by the Reactive Extensions RxJS library.
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
Our QuickStart doesn't use the Reactive Extensions
|
|
||||||
but any substantial application will want them
|
|
||||||
when working with observables.
|
|
||||||
We added the library here in QuickStart so we don't forget later.
|
|
||||||
:marked
|
|
||||||
Finally, we loaded the web development version of Angular 2 itself.
|
|
||||||
|
|
||||||
We'll make different choices as we gain experience and
|
|
||||||
become more concerned about production qualities such as
|
|
||||||
load times and memory footprint.
|
|
||||||
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
<a id="package-json"></a>
|
|
||||||
## Appendix: package.json
|
|
||||||
|
|
||||||
[npm](https://docs.npmjs.com/) is a popular package manager and Angular application developers rely on it
|
|
||||||
to acquire and manage the libraries their apps require.
|
|
||||||
|
|
||||||
We specify the packages we need in an npm [package.json](https://docs.npmjs.com/files/package.json) file.
|
|
||||||
|
|
||||||
The Angular team suggests the packages listed in the `dependencies` and `devDependencies`
|
|
||||||
sections listed in this file:
|
|
||||||
|
|
||||||
+makeJson('quickstart/ts/package.1.json',{ paths: 'dependencies, devDependencies'}, 'package.json (dependencies)')(format=".")
|
|
||||||
:marked
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
There are other possible package choices.
|
|
||||||
We're recommending this particular set that we know work well together.
|
|
||||||
Play along with us for now.
|
|
||||||
Feel free to make substitutions later to suit your tastes and experience.
|
|
||||||
:marked
|
|
||||||
A `package.json` has an optional **scripts** section where we can define helpful
|
|
||||||
commands to perform development and build tasks.
|
|
||||||
We've included a number of such scripts in our suggested `package.json`:
|
|
||||||
+makeJson('quickstart/ts/package.1.json',{ paths: 'scripts'}, 'package.json (scripts)')(format=".")
|
|
||||||
:marked
|
|
||||||
We've seen how we can run the compiler and a server at the same time with this command:
|
|
||||||
code-example(format="").
|
|
||||||
npm start
|
|
||||||
:marked
|
|
||||||
We execute npm scripts in that manner: `npm run` + *script-name*. Here's what these scripts do:
|
|
||||||
|
|
||||||
* `npm run tsc` - run the TypeScript compiler once
|
|
||||||
|
|
||||||
* `npm run tsc:w` - run the TypeScript compiler in watch mode;
|
|
||||||
the process keeps running, awaiting changes to TypeScript files and re-compiling when it sees them.
|
|
||||||
|
|
||||||
* `npm run lite` - run the [lite-server](https://www.npmjs.com/package/lite-server),
|
|
||||||
a light-weight, static file server, written and maintained by [John Papa](http://johnpapa.net/)
|
|
||||||
with excellent support for Angular apps that use routing.
|
|
||||||
|
|
||||||
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
<a id="npm-errors"></a>
|
|
||||||
## Appendix: Npm errors and warnings
|
|
||||||
|
|
||||||
All is well if there are no console messages starting with `npm ERR!` *at the end* of **npm install**.
|
|
||||||
There might be a few `npm WARN` messages along the way — and that is perfectly fine.
|
|
||||||
|
|
||||||
We often see an `npm WARN` message after a series of `gyp ERR!` messages.
|
|
||||||
Ignore them. A package may try to re-compile itself using `node-gyp`.
|
|
||||||
If the re-compile fails, the package recovers (typically with a pre-built version)
|
|
||||||
and everything works.
|
|
||||||
|
|
||||||
Just make sure there are no `npm ERR!` messages at the very end of `npm install`.
|
|
||||||
|
|
||||||
<!-- Move this to the Style Guide when we have one -->
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
<a id="tsconfig"></a>
|
|
||||||
## Appendix: TypeScript configuration
|
|
||||||
We added a TypeScript configuration file (`tsconfig.json`) to our project to
|
|
||||||
guide the compiler as it generates JavaScript files.
|
|
||||||
Get details about `tsconfig.json` from the official
|
|
||||||
[TypeScript wiki](https://github.com/Microsoft/TypeScript/wiki/tsconfig.json).
|
|
||||||
|
|
||||||
The options and flags in the file we provided are essential.
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
In this QuickStart and many of the other samples 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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
<a id="typings"></a>
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
## Appendix: TypeScript Typings
|
|
||||||
Many libraries such as jQuery, the Jasmine testing library, and Angular itself,
|
|
||||||
add material to the JavaScript environment that the TypeScript compiler doesn't recognize.
|
|
||||||
When the compiler doesn't recognize something, it throws an error.
|
|
||||||
|
|
||||||
We use [TypeScript type definition files](http://www.typescriptlang.org/Handbook#writing-dts-files)
|
|
||||||
— *d.ts files* — to tell the compiler about the libraries we load.
|
|
||||||
|
|
||||||
TypeScript-aware editors leverage these same definition files to display type information about library features.
|
|
||||||
|
|
||||||
Many libraries include their definition files in their npm packages where both the TypeScript compiler and editors
|
|
||||||
can find them. Angular is one such library.
|
|
||||||
Peek into the `node_modules/angular2/` folder to see several `...d.ts` files that describe parts of Angular.
|
|
||||||
|
|
||||||
**We do nothing to get *typings* files for library packages with bundled *d.ts* files.**
|
|
||||||
|
|
||||||
Sadly, many libraries — jQuery, Jasmine, and Lodash among them — do *not* include `d.ts` files in their npm packages.
|
|
||||||
Fortunately, either their authors or community contributors have created separate *d.ts* files for these libraries and
|
|
||||||
published them in well-known locations.
|
|
||||||
The *typings* tool can find and fetch these files for us.
|
|
||||||
|
|
||||||
We installed the [typings](https://github.com/typings/typings/blob/master/README.md) tool
|
|
||||||
with npm (find it in the `package.json`) and added an npm script
|
|
||||||
to run that tool automatically after *npm* installation completes.
|
|
||||||
+makeJson('quickstart/ts/package.1.json', {paths: 'scripts.postinstall'}, 'package.json (postinstall)')(format=".")
|
|
||||||
:marked
|
|
||||||
This *typings* tool command installs the *d.ts* files that we identified in `typings.json`:
|
|
||||||
+makeJson('quickstart/ts/typings.1.json', null, 'typings.json')(format=".")
|
|
||||||
:marked
|
|
||||||
We identified only one *typings* file in this QuickStart, the *d.ts* file for
|
|
||||||
[es6-shim](https://github.com/paulmillr/es6-shim/blob/master/README.md) that brings ES2015/ES6
|
|
||||||
capabilities to our ES5 browsers.
|
|
||||||
QuickStart itself doesn't need this shim but many of the documentation samples do
|
|
||||||
and most of us would be disappointed if typical ES2015 features didn't work out-of-the-box.
|
|
||||||
|
|
||||||
We can also run the *typings* tool ourselves. The following command lists the locally installed typings files.
|
|
||||||
code-example(format="").
|
|
||||||
npm run typings -- list
|
|
||||||
:marked
|
|
||||||
The following command installs the typings file for the Jasmine test library and updates the `typings.config`
|
|
||||||
so we that we get it automatically the next time.
|
|
||||||
code-example(format="").
|
|
||||||
npm run typings -- install jasmine --ambient --save
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
The [–– option](https://docs.npmjs.com/cli/run-script) is important;
|
|
||||||
it tells npm to pass all arguments to the right of `--` to the *typings* command.
|
|
||||||
|
|
||||||
Learn about the features of the *typings* tool at its [site on github](https://github.com/typings/typings/blob/master/README.md).
|
|
||||||
:marked
|
|
||||||
#### Typing file collisions
|
|
||||||
|
|
||||||
The TypeScript compiler does not tolerate redefinition of a type. For example, it throws an error if it's given two definitions for
|
|
||||||
the `Promise` type.
|
|
||||||
|
|
||||||
Double definitions are common. In fact, the `typings` tool deliberately creates
|
|
||||||
duplicate sets of typings (for reasons best explained elsewhere).
|
|
||||||
Look in the project structure for the *typings folder* where we should find something like:
|
|
||||||
.filetree
|
|
||||||
.file typings
|
|
||||||
.children
|
|
||||||
.file browser
|
|
||||||
.children
|
|
||||||
.file ambient
|
|
||||||
.children
|
|
||||||
.file es6-shim
|
|
||||||
.children
|
|
||||||
.file es6-shim.d.ts
|
|
||||||
.children
|
|
||||||
.file main
|
|
||||||
.children
|
|
||||||
.file ambient
|
|
||||||
.children
|
|
||||||
.file es6-shim
|
|
||||||
.children
|
|
||||||
.file es6-shim.d.ts
|
|
||||||
.children
|
|
||||||
.file browser.d.ts
|
|
||||||
.file main.d.ts
|
|
||||||
:marked
|
|
||||||
The `es6-shim` typings are duplicated and the `browser.d.ts` and `main.d.ts` have overlapping content.
|
|
||||||
|
|
||||||
We must tell the compiler to ignore one or the other.
|
|
||||||
We removed the `main` set from consideration in the `exclude` section of our `tsconfig.json` file:
|
|
||||||
+makeJson('quickstart/ts/tsconfig.1.json', {paths: 'exclude'}, 'tsconfig.json (exclude)')(format=".")
|
|
||||||
:marked
|
|
||||||
|
|
||||||
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
<a id="systemjs"></a>
|
|
||||||
## Appendix: SystemJS Configuration
|
|
||||||
|
|
||||||
The QuickStart uses [SystemJS](https://github.com/systemjs/systemjs) to load application
|
|
||||||
and library modules.
|
|
||||||
There are alternatives that work just fine including the well-regarded [webpack](https://webpack.github.io/).
|
|
||||||
SystemJS happens to be a good choice but we want to be clear that it was a choice and not a preference.
|
|
||||||
|
|
||||||
All module loaders require configuration and all loader configuration
|
|
||||||
becomes complicated rather quickly as soon as the file structure diversifies and
|
|
||||||
we start thinking about building for production and performance.
|
|
||||||
|
|
||||||
We suggest becoming well-versed in the loader of your choice.
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
Learn more about SystemJS configuration [here](https://github.com/systemjs/systemjs/blob/master/docs/config-api.md).
|
|
||||||
:marked
|
|
||||||
With those cautions in mind, what are we doing here?
|
|
||||||
+makeExample('quickstart/ts/index.html', 'systemjs', 'index.html (System configuration)')(format=".")
|
|
||||||
:marked
|
|
||||||
The `packages` node tells SystemJS what to do when it sees a request for a
|
|
||||||
module from the `app/` folder.
|
|
||||||
|
|
||||||
Our QuickStart makes such requests when one of its
|
|
||||||
application TypeScript files has an import statement like this:
|
|
||||||
+makeExample('quickstart/ts/app/main.ts', 'app-component', 'main.ts (excerpt)')(format=".")
|
|
||||||
:marked
|
|
||||||
Notice that the module name (after `from`) does not mention a filename extension.
|
|
||||||
The `packages:` configuration tells SystemJS to default the extension to 'js', a JavaScript file.
|
|
||||||
|
|
||||||
That makes sense because we transpile TypeScript to JavaScript
|
|
||||||
*before* running the application.
|
|
||||||
|
|
||||||
.l-sub-section
|
|
||||||
:marked
|
|
||||||
In the live example on plunker we transpile (AKA compile) to JavaScript in the browser
|
|
||||||
on the fly. That's fine for a demo. That's not our preference for development or production.
|
|
||||||
|
|
||||||
We recommend transpiling (AKA compiling) to JavaScript during a build phase
|
|
||||||
before running the application for several reasons including:
|
|
||||||
|
|
||||||
* We see compiler warnings and errors that are hidden from us in the browser.
|
|
||||||
|
|
||||||
* Pre-compilation simpifies the module loading process and
|
|
||||||
it's much easier to diagnose problem when this is a separate, external step.
|
|
||||||
|
|
||||||
* Pre-compilation means a faster user experience because the browser doesn't waste time compiling.
|
|
||||||
|
|
||||||
* We iterate development faster because we only re-compile changed files.
|
|
||||||
We notice the difference as soon as the app grows beyond a handful of files.
|
|
||||||
|
|
||||||
* Pre-compilation fits into a continuous integration process of build, test, deploy.
|
|
||||||
:marked
|
|
||||||
The `System.import` call tells SystemJS to import the `main` file
|
|
||||||
(`main.js` ... after transpiling `main.ts`, remember?).
|
|
||||||
`main` is where we tell Angular to launch the application.
|
|
||||||
We also catch and log launch errors to the console.
|
|
||||||
|
|
||||||
All other modules are loaded upon request
|
|
||||||
either by an import statement or by Angular itself.
|
|
||||||
|
|
||||||
.l-main-section
|
|
||||||
:marked
|
|
||||||
<a id="main"></a>
|
|
||||||
## Appendix: **main.ts**
|
|
||||||
|
|
||||||
### Bootstrapping is platform-specific
|
|
||||||
We import the `bootstrap` function from `angular2/platform/browser`,
|
|
||||||
not `angular2/core`. There's a good reason.
|
|
||||||
|
|
||||||
We only call "core" those capabilities that are the same across all platform targets.
|
|
||||||
True, most Angular applications run only in a browser and we'll call the bootstrap function from
|
|
||||||
this library most of the time. It's pretty "core" if we're always writing for a browser.
|
|
||||||
|
|
||||||
But it is possible to load a component in a different enviroment.
|
|
||||||
|
|
||||||
We might load it on a mobile device with [Apache Cordova](https://cordova.apache.org/) or [NativeScript](https://www.nativescript.org/).
|
|
||||||
|
|
||||||
We might wish to render the first page of our application on the server
|
|
||||||
to improve launch performance or facilitate
|
|
||||||
[SEO](http://static.googleusercontent.com/media/www.google.com/en//webmasters/docs/search-engine-optimization-starter-guide.pdf).
|
|
||||||
|
|
||||||
These targets require a different kind of bootstrap function that we'd import from a different library.
|
|
||||||
|
|
||||||
### Why do we create a separate ***main.ts*** file?
|
|
||||||
|
|
||||||
The *main.ts* file is tiny. This is just a QuickStart.
|
|
||||||
We could have folded its few lines into the `app.component` file
|
|
||||||
and spared ourselves some complexity.
|
|
||||||
|
|
||||||
We didn't for what we believe to be good reasons:
|
|
||||||
1. Doing it right is easy
|
|
||||||
1. Testability
|
|
||||||
1. Reusability
|
|
||||||
1. Separation of concerns
|
|
||||||
1. We learned about import and export
|
|
||||||
|
|
||||||
### It's easy
|
|
||||||
Sure it's an extra step and an extra file. How hard is that in the scheme of things?
|
|
||||||
|
|
||||||
We'll see that a separate `main.ts` is beneficial for *most* apps
|
|
||||||
even if it isn't critical for the QuickStart.
|
|
||||||
Let's develop good habits now while the cost is low.
|
|
||||||
|
|
||||||
### Testability
|
|
||||||
We should be thinking about testability from the beginning
|
|
||||||
even if we know we'll never test the QuickStart.
|
|
||||||
|
|
||||||
It is difficult to unit test a component when there is a call to `bootstrap` in the same file.
|
|
||||||
As soon as we load the component file to test the component,
|
|
||||||
the `bootstrap` function tries to load the application in the browser.
|
|
||||||
It throws an error because we're not expecting to run the entire application,
|
|
||||||
just test the component.
|
|
||||||
|
|
||||||
Relocating the `bootstrap` function to `main.ts` eliminates this spurious error
|
|
||||||
and leaves us with a clean component module file.
|
|
||||||
|
|
||||||
### Reusability
|
|
||||||
We refactor, rename, and relocate files as our application evolves.
|
|
||||||
We can't do any of those things while the file calls `bootstrap`.
|
|
||||||
We can't move it.
|
|
||||||
We can't reuse the component in another application.
|
|
||||||
We can't pre-render the component on the server for better performance.
|
|
||||||
|
|
||||||
### Separation of concerns
|
|
||||||
A component's responsibility is to present and manage a view.
|
|
||||||
|
|
||||||
Launching the application has nothing to do with view management.
|
|
||||||
That's a separate concern. The friction we're encountering in testing and reuse
|
|
||||||
stems from this unnecessary mix of responsibilities.
|
|
||||||
|
|
||||||
### Import/Export
|
|
||||||
|
|
||||||
While writing a separate `main.ts` file we learned an essential Angular skill:
|
|
||||||
how to export from one module and import into another.
|
|
||||||
We'll do a lot of that as we learn more Angular.
|
|
||||||
|
@ -139,7 +139,29 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.verbose {
|
||||||
|
font-size: ($unit * 3);
|
||||||
|
@media handheld and (max-width: $phone-breakpoint),
|
||||||
|
screen and (max-device-width: $phone-breakpoint),
|
||||||
|
screen and (max-width: $tablet-breakpoint) {
|
||||||
|
font-size: ($unit * 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button.verbose.on {display: none}
|
||||||
|
|
||||||
|
.l-verbose-section {
|
||||||
|
margin: 0px 0px ($unit * 4) 0px;
|
||||||
|
padding-left: ($unit * 2);
|
||||||
|
//background: lighten($light, 5%);
|
||||||
|
border-left: ($unit / 6) solid $grey;
|
||||||
|
border-radius: ($unit / 6);
|
||||||
|
}
|
||||||
|
.l-verbose-inherit {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border-left: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Margins & Padding
|
* Margins & Padding
|
||||||
|
Loading…
x
Reference in New Issue
Block a user